在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Linux/ 大于小于號差別?
別人echo、你也echo,是問echo知多少?
何為 shell?
你要 if 還是 case 呢?
""(雙引號) 與''(單引號) 差在哪?
exec 跟 source 差在哪?
$(())與$()還有${}差在哪?
() 與 {} 差在哪?
shell and Carriage 關(guān)系
for what? while 與 until 差在哪?
大于小于號差別?
[^ ] 跟[! ]差在哪? (RE: Regular Expression)
[^ ] 跟[! ]差在哪? (wildcard)
特殊符號差異
&& 與 || 差在哪?
var=value 在 export 前后的差在哪?

大于小于號差別?

這次的題目,之前我在 CU 的 shell 版說明過了: (原帖的連接在論壇改版后,已經(jīng)失效) 這次我就不重寫了,將帖子的內(nèi)容 “抄” 下來就是了...

文件描述符 (fd, File Descriptor)

談到I/O redirection,不妨先讓我們認識一下File Descriptor(fd,文件描述符)。

進程的運算,在大部分情況下,都是進行數(shù)據(jù) (data) 的處理, 這些數(shù)據(jù)從哪里,讀進來?又輸出到哪里呢? 這就是 file descriptor(fd) 的功用了。

在 shell 的進程中,最常使用的fd大概有三個,分別為:

  • 0:standard Input (STDIN)
  • 1: standard output(STDOUT)
  • 2: standard Error output (STDERR

在標準情況下,這些 fd 分別跟如下設備 (device) 關(guān)聯(lián):

  • stdin(0): keyboard
  • stdout(1): monitor
  • stderr(2): monitor

Tips: linux 中的文件描述符 (fd) 用整數(shù)表示。 linux 中任何一個進程都默認打開三個文件, 這三個文件對應的文件描述符分別是:0, 1, 2; 即 stdin, stdout, stderr.

我們可以用如下命令測試一下:

$ mail -s test root
this is a test mail。
please skip.
^d (同時按下ctrl 跟d鍵)

很明顯,mail進程所讀進的數(shù)據(jù),就是從 stdin 也就是 keyboard 讀進的。 不過,不見得每個進程的stdin都跟mail一樣 從keyboard讀進,因為進程的作者可以從文件參數(shù)讀進stdin, 如:

$ cat /etc/passwd

但,要是cat之后沒有文件參數(shù)則如何呢? 哦, 請你自己玩玩看...^_^

$ cat

Tips:

請留意數(shù)據(jù)輸出到哪里去了, 最后別忘了按ctrl+d(^d), 退出 stdin 輸入。

至于stdoutstderr,嗯... 等我有空再續(xù)吧...^_^ 還是,有哪位前輩來玩接龍呢?

相信,經(jīng)過上一個練習后, 你對stdinstdout應該不難理解了吧? 然后,讓我們看看stderr好了。

事實上,stderr沒什么難理解的: 說白了就是 “錯誤信息” 要往哪里輸出而已... 比方說, 若讀進的文件參數(shù)不存在的, 那我們在 monitor 上就看到了:

$ ls no.such.file
ls: no.such.file: No such file or directory

若同一個命令,同時成生stdoutstderr呢? 那還不簡單,都送到 monitor 來就好了:

$ touch my.file
$ ls my.file on.such.file
ls: no.such.file: No such file or directory
my.file

okay, 至此,關(guān)于 fd 及其名稱、還有相關(guān)聯(lián)的設備, 相信你已經(jīng)沒問題了吧?

I/O 重定向 (I/O Redirection)

那好,接下來讓我們看看如何改變這些 fd 的預設數(shù)據(jù)通道。

  • <來改變讀進的數(shù)據(jù)通道 (stdin),使之從指定的文件讀進。
  • >來改變輸出的數(shù)據(jù)通道 (stdout,stderr), 使之輸出到指定的文件。

輸入重定向n<(input redirection)

比方說:

$ cat < my.file

就是從 my.file 讀入數(shù)據(jù)

$ mail -s test root < /etc/passwd

則是從 / etc/passwd 讀入...

這樣一來,stdin 將不再是從 keyboard 讀入, 而是從指定的文件讀入了...

嚴格來說,<符號之前需要指定一個 fd 的 (之前不能有空白),但因為 0 是<的預設值,因此,<0<是一樣的 。

okay,這樣好理解了吧?

那要是用兩個<,即<<又是啥呢? 這是所謂的here document,它可以讓我們輸入一段文本,直到讀到<< 后指定的字符串。

比方說:

$ cat <<EOF
first line here
second line here
third line here
EOF

這樣的話,cat會讀入 3 個句子, 而無需從 keyboard 讀進數(shù)據(jù)且要等到 (ctrl+d, ^d) 結(jié)束輸入。

重定向輸出>n(output redirection)

當你搞懂了0< 原來就是改變stdin的數(shù)據(jù)輸入通道之后, 相信要理解如下兩個 redirection 就不難了:

  • 1> #改變 stdout 的輸出通道;
  • 2> #改變 stderr 的輸出通道;

兩者都是將原來輸出到 monitor 的數(shù)據(jù), 重定向輸出到指定的文件了。

由于 1 是>的預設值, 因此,1>>是相同的,都是改變stdout。

用上次的 ls 的例子說明一下好了:

$ ls my.file no.such.file 1>file.out
ls: no.such.file: No such file or directory

這樣 monitor 的輸出就只剩下stderr的輸出了, 因為stdout重定向輸出到文件 file.out 去了。

$ ls my.file no.such.file 2>file.err
my.file

這樣 monitor 就只剩下了stdout, 因為stderr重定向輸出到文件 file.err 了。

$ ls my.file no.such.file 1>file.out 2>file.err

這樣 monitor 就啥也沒有了, 因為stdoutstderr都重定向輸出到文件了。

呵呵,看來要理解>一點也不難啦是不? 沒騙你吧? ^_^ 不過有些地方還是要注意一下的。

$ ls my.file no.such.file 1>file.both 2>file.both

假如stdout(1) 與stderr(2) 都同時在寫入 file.both 的話, 則是采取 "覆蓋" 的方式:后來寫入覆蓋前面的。

讓我們假設一個stdoutstderr同時寫入到 file.out 的情形好了;

  • 首先stdout寫入 10 個字符
  • 然后stderr寫入 6 個字符

那么,這時原本的stdout輸出的 10 個字符, 將被stderr輸出的 6 個字符覆蓋掉了。

那如何解決呢?所謂山不轉(zhuǎn)路轉(zhuǎn),路不轉(zhuǎn)人轉(zhuǎn)嘛, 我們可以換一個思維: 將stderr導進stdout 或者將stdout導進到stderr, 而不是大家在搶同一份文件,不就行了。 bingo 就是這樣啦:

  • 2>&1 #將stderr并進stdout輸出
  • 1>&2 或者 >&2 #將stdout并進stderr輸出。

這樣,不就皆大歡喜了嗎? ~~~ ^_^

不過,光解決了同時寫入的問題還不夠, 我們還有其他技巧需要了解的。 故事還沒有結(jié)束,別走開廣告后,我們在回來....

I/O 重定向與 linux 中的/dev/null

okay,這次不講 I/O Redirection, 請佛吧... (有沒有搞錯?網(wǎng)中人是否頭殼燒壞了?...) 嘻~~~^_^

學佛的最高境界,就是 "四大皆空"。 至于是空哪四大塊,我也不知,因為我還沒有到那個境界.. 這個 “空” 字, 卻非常值得反復把玩: --- 色即是空,空即是色 好了,施主要是能夠領會 "空" 的禪意,那離修成正果不遠了。

在 linux 的文件系統(tǒng)中,有個設備文件: /dev/null。許多人都問過我,那是什么玩意兒? 我跟你說好了,那就是 "空" 啦。

沒錯空空如也的空就是 null 了... 請問施主是否忽然有所頓悟了呢? 然則恭喜了。

這個 null 在 I/O Redirection 中可有用的很呢?

  • 將 fd 1跟 fd 2重定向到 / dev/null 去,就可忽略 stdout, stderr 的輸出。
  • 將 fd 0重定向到 / dev/null,那就是讀進空 (nothing)。

比方說,我們在執(zhí)行一個進程時,會同時輸出到 stdout 與 stderr, 假如你不想看到 stderr(也不想存到文件), 那就可以:

$ ls my.file no.such.file 2>/dev/null
my.file

若要相反:只想看到 stderr 呢? 還不簡單將 stdout,重定向的 / dev/null 就行:

$ ls my.file no.such.file >/dev/null
ls: no.such.file: No such file or directory

那接下來,假如單純的只跑進程,而不想看到任何輸出呢? 哦,這里留了一手,上次沒講的法子, 專門贈與有緣人... ^_^ 除了用 >/dev/null 2>&1之外,你還可以如此:

$ ls my.file no.such.file &>/dev/null```

>**Tips:**
>
>將 &> 換成 >& 也行!

### 重定向輸出 append (>>)

okay? 請完佛,接下來,再讓我們看看如下情況:

$ echo "1" > file.out $ cat file.out 1 $ echo "2" > file.out $ cat file.out 2


看來,我們在重定向 stdout 或 stderr 進一個文件時, 似乎永遠只能獲得最后一次的重定向的結(jié)果. 那之前的內(nèi)容呢?

呵呵,要解決這個問題,很簡單啦,將`>`換成`>>` 就好了;

$ echo "3" >> file.out $ cat file.out 2 3


如此一來,被重定向的文件的之前的內(nèi)容并不會丟失, 而新的內(nèi)容則一直追加在最后面去。so easy?...

但是,只要你再次使用`>`來重定向輸出的話, 那么,原來文件的內(nèi)容被 truncated(清洗掉)。 這是,你要如何避免呢? ---- 備份, yes,我聽到了,不過,還有更好的嗎? 既然與施主這么有緣分,老衲就送你一個錦囊妙法吧:

$ set -o noclobber $ echo "4" > file.out -bash:file: cannot overwrite existing file.


那,要如何取消這個限制呢? 哦,將`set -o`換成 `set +o`就行了:

$ set +o noclobber $ echo "5" > file.out $ cat file.out 5


再問:那有辦法不取消而又 “臨時” 改寫目標文件嗎? 哦,佛曰:不可告也。 啊,~ 開玩笑的,開玩笑啦~^_^, 哎,早就料到人心是不足的了

$ set -o noclobber $ echo "6" >| file.out $ cat file.out 6


留意到?jīng)]有: **在`>`后面加個`|`就好, 注意: `>`與`|`之間不能有空白哦**...

### I/O Redirection 的優(yōu)先級

呼....(深呼吸吐納一下吧)~~~ ^_^ 再來還有一個難題要你去參透呢:

$ echo "some text here" >file $ cat < file some text here $cat < file >file.bak $cat < file.bak some text here $cat < file >file


嗯?注意到?jīng)]有? --- 怎么最后那個 cat 命令看到 file 是空的呢? why? why? why?

前面提到:`$cat < file > file`之后, 原本有內(nèi)容的文件,結(jié)果卻被清空了。 要理解這個現(xiàn)象其實不難, 這只是 priority 的問題而已: ** 在 IO Redirection 中, stdout 與 stderr 的管道先準備好, 才會從 stdin 讀入數(shù)據(jù)。** 也就是說,在上例中,`>file`會將 file 清空, 然后才讀入 `< file`。 但這時候文件的內(nèi)容已被清空了,因此就變成了讀不進任何數(shù)據(jù)。

哦,~ 原來如此~^_^ 那... 如下兩例又如何呢?

$ cat <> file $ cat < file >>file



嗯... 同學們,這兩個答案就當練習題嘍, 下課前交作業(yè)。

>**Tips:** 我們了解到`>file`能夠快速把文件 file 清空; 或者使用`:>file`同樣可以清空文件,`:>file`與`>file`的功能: 若文件 file 存在,則將 file 清空; 否則,創(chuàng)建空文件 file (等效于`touch file`); 二者的差別在于`>file`的方式不一定在所有的 shell 的都可用。
>
`exec 5<>file; echo "abcd" >&5; cat <&5` 將 file 文件的輸入、輸出定向到文件描述符 5, 從而描述符 5 可以接管 file 的輸入輸出; 因此,`cat <>file`等價于`cat < file`。
>
>而`cat < file >>file`則使 file 內(nèi)容成幾何級數(shù)增長。

好了, I/O Redirection 也快講完了, sorry, 因為我也只知道這么多而已啦~ 嘻~^_^ 不過,還有一樣東東是一定要講的,各位觀眾 (請自行配樂~!#@$%): 就是 pipe line 也。

### 管道 (pipe line)

談到`pipe line`,我相信不少人都不會陌生: 我們在很多 command line 上??吹絗|`符號就是 pipe line 了。

不過,pipe line 究竟是什么東東呢? 別急別急... 先查一下英文字典,看看 pipe 是什么意思? 沒錯他就是 “水管” 的意思... 那么,你能想象一下水管是怎樣一個根接一根的嗎? 又, 每根水管之間的 input 跟 output 又如何呢? 靈光一閃:原來 pipe line 的 I/O 跟水管的 I/O 是一模一樣的: **上一個命令的 stdout 接到下一個命令的 stdin 去了** 的確如此。不管在 command line 上使用了多少個 pipe line, 前后兩個 command 的 I/O 是彼此連接的 (恭喜:你終于開放了 ^_^)

不過... 然而... 但是... ...stderr 呢? 好問題不過也容易理解: 若水管漏水怎么辦? 也就是說:在 pipe line 之間, 前一個命令的 stderr 是不會接進下一個命令的 stdin 的, 其輸出,若不用 2>file 的話,其輸出在 monitor 上來。 這點請你在 pipe line 運用上務必要注意的。

那,或許你有會問: **有辦法將 stderr 也喂進下一個命令的 stdin 嗎?** (貪得無厭的家伙),方法當然是有的,而且,你早已學習過了。 提示一下就好:** 請問你如何將 stderr 合并進 stdout 一同輸出呢? 若你答不出來,下課后再來問我...(如果你臉皮足夠厚的話...)

或許,你仍意猶未盡,或許,你曾經(jīng)碰到過下面的問題: 在`cmd1 | cmd2 | cmd3 | ... `這段 pipe line 中如何將 cmd2 的輸出保存到一個文件呢?

若你寫成`cmd1 | cmd2 >file | cmd3`的話, 那你肯定會發(fā)現(xiàn)`cmd3`的 stdin 是空的,(當然了,你都將 水管接到別的水池了) 聰明的你或許會如此解決:

`cmd1 | cmd2 >file; cmd3 < file`

是的,你可以這樣做,但最大的壞處是: file I/O 會變雙倍,在 command 執(zhí)行的整個過程中, file I/O 是最常見的最大效能殺手。 凡是有經(jīng)驗的 shell 操作者,都會盡量避免或降低 file I/O 的頻度。

那上面問題還有更好的方法嗎? 有的,那就是`tee`命令了。 **所謂的`tee`命令是在不影響原本 I/O 的情況下, 將 stdout 賦值到一個文件中去**。 因此,上面的命令行,可以如此執(zhí)行:

`cmd1 | cmd2 | tee file | cmd3`

在預設上,`tee`會改寫目標文件, 若你要改為追加內(nèi)容的話,那可用 - a 參數(shù)選項。

基本上,pipe line 的應用在 shell 操作上是非常廣泛的。 尤其是在 text filtering 方面, 如,cat, more, head, tail, wc, expand, tr, grep, sed, awk... 等等文字處理工具。 搭配起 pipe line 來使用,你會覺得 command line 原來活得如此精彩的。 常讓人有 “眾里尋他千百度,驀然回首,那人卻在燈火闌珊處” 之感...

好了,關(guān)于 I/O Redirection 的介紹就到此告一段落。 若日后,有空的話,在為大家介紹其他在 shell 上好玩的東西。