linux學習篇8---- 《鳥哥的Linux私房菜基礎學習篇(第三版)》讀書筆記
數據流重導向
standard output 與 standard error output
標準輸出指的是『命令運行所回傳的正確的信息』,而標準錯誤輸出可理解爲『 命令運行失敗後,所回傳的錯誤信息』
不管正確或錯誤的數據都是默認輸出到屏幕上,所以屏幕當然是亂亂的!那能不能透過某些機制將這兩股數據分開呢? 當然可以啊!那就是數據流重導向的功能啊!數據流重導向可以將 standard output (簡稱 stdout) 與 standard error output (簡稱 stderr) 分別傳送到其他的文件或裝置去,而分別傳送所用的特殊字符則如下所示:
- 標準輸入 (stdin) :代碼爲 0 ,使用 < 或 << ;
- 標準輸出 (stdout):代碼爲 1 ,使用 > 或 >> ;
- 標準錯誤輸出(stderr):代碼爲 2 ,使用 2> 或 2>> ;
爲了理解 stdout 與 stderr ,我們先來進行一個範例的練習:
範例一:觀察你的系統根目錄 (/) 下各目錄的文件名、權限與屬性,並記錄下來 [root@www ~]# ll / <==此時屏幕會顯示出文件名信息 [root@www ~]# ll / > ~/rootfile <==屏幕並無任何信息 [root@www ~]# ll ~/rootfile <==有個新檔被創建了! -rw-r--r-- 1 root root 1089 Feb 6 17:00 /root/rootfile
文件的創建方式是:
- 該文件 (本例中是 ~/rootfile) 若不存在,系統會自動的將他創建起來
- 當這個文件存在的時候,那麼系統就會先將這個文件內容清空,然後再將數據寫入!
- 也就是若以 > 輸出到一個已存在的文件中,那個文件就會被覆蓋掉!
- 若以>>輸出到一個文件中,這文件原來的內容會保留下來!
範例四:承範例三,將錯誤的數據丟棄,屏幕上顯示正確的數據 [dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null /home/dmtsai/.bashrc <==只有 stdout 會顯示到屏幕上, stderr 被丟棄了
將正確與錯誤數據通通寫入同一個文件
範例五:將命令的數據全部寫入名爲 list 的文件中 [dmtsai@www ~]$ find /home -name .bashrc > list 2> list <==錯誤 [dmtsai@www ~]$ find /home -name .bashrc > list 2>&1 <==正確 [dmtsai@www ~]$ find /home -name .bashrc &> list <==正確
standard input : < 與 <<
將原本需要由鍵盤輸入的數據,改由文件內容來取代
範例六:利用 cat 命令來創建一個文件的簡單流程 [root@www ~]# cat > catfile testing cat file test <==這裏按下 [ctrl]+d 來離開 [root@www ~]# cat catfile testing cat file test
由於加入 > 在 cat 後,所以那個 catfile 會被主動的創建,而內容就是剛剛鍵盤上面輸入的那兩行數據
範例七:用 stdin 取代鍵盤的輸入以創建新文件的簡單流程 [root@www ~]# cat > catfile < ~/.bashrc [root@www ~]# ll catfile ~/.bashrc -rw-r--r-- 1 root root 194 Sep 26 13:36 /root/.bashrc -rw-r--r-- 1 root root 194 Feb 6 18:29 catfile # 注意看,這兩個文件的大小會一模一樣!幾乎像是使用 cp 來複制一般!<< 這個連續兩個小於的符號代表的是結束的輸入字符
[root@www ~]# cat > catfile << "eof" > This is a test. > OK now stop > eof <==輸入這關鍵詞,立刻就結束而不需要輸入 [ctrl]+d [root@www ~]# cat catfile This is a test. OK now stop <==只有這兩行,不會存在關鍵詞那一行!
命令運行的判斷依據: ; , &&, ||
cmd ; cmd (不考慮命令相關性的連續命令下達)
分號前的命令運行完後就會立刻接着運行後面的命令
$?
(命令回傳值) 與 && 或 ||
命令下達情況 | 說明 |
cmd1 && cmd2 | 1. 若 cmd1 運行完畢且正確運行($?=0),則開始運行 cmd2。 2. 若 cmd1 運行完畢且爲錯誤 ($?≠0),則 cmd2 不運行。 |
cmd1 || cmd2 | 1. 若 cmd1 運行完畢且正確運行($?=0),則 cmd2 不運行。 2. 若 cmd1 運行完畢且爲錯誤 ($?≠0),則開始運行 cmd2。 |
例題:
command1 && command2 || command3 順序不能變
管線命令
(pipe)
[root@www ~]# ls -al /etc | less
- 管線命令僅會處理 standard output,對於 standard error output 會予以忽略
- 管線命令必須要能夠接受來自前一個命令的數據成爲 standard input 繼續處理才行。
[root@www ~]# cut -d'分隔字符' -f fields <==用於有特定分隔字符 [root@www ~]# cut -c 字符區間 <==用於排列整齊的信息 選項與參數: -d :後面接分隔字符。與 -f 一起使用; -f :依據 -d 的分隔字符將一段信息分割成爲數段,用 -f 取出第幾段的意思; -c :以字符 (characters) 的單位取出固定字符區間; 範例一:將 PATH 變量取出,我要找出第五個路徑。 [root@www ~]# echo $PATH /bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games: # 1 | 2 | 3 | 4 | 5 | 6 | 7 [root@www ~]# echo $PATH | cut -d ':' -f 5 # 如同上面的數字顯示,我們是以『 : 』作爲分隔,因此會出現 /usr/local/bin
cut處理的信息是以『行』爲單位
範例二:將 export 輸出的信息,取得第 12 字符以後的所有字符串 [root@www ~]# export declare -x HISTSIZE="1000" declare -x INPUTRC="/etc/inputrc" declare -x KDEDIR="/usr" declare -x LANG="zh_TW.big5" .....(其他省略)..... # 注意看,每個數據都是排列整齊的輸出!如果我們不想要『 declare -x 』時, # 就得這麼做: [root@www ~]# export | cut -c 12- HISTSIZE="1000" INPUTRC="/etc/inputrc" KDEDIR="/usr" LANG="zh_TW.big5" .....(其他省略)..... # 知道怎麼回事了吧?用 -c 可以處理比較具有格式的輸出數據! # 我們還可以指定某個範圍的值,例如第 12-20 的字符,就是 cut -c 12-20 等等!grep:
[root@www ~]# grep [-acinv] [--color=auto] '搜尋字符串' filename 選項與參數: -a :將 binary 文件以 text 文件的方式搜尋數據 -c :計算找到 '搜尋字符串' 的次數 -i :忽略大小寫的不同,所以大小寫視爲相同 -n :順便輸出行號 -v :反向選擇,亦即顯示出沒有 '搜尋字符串' 內容的那一行! --color=auto :可以將找到的關鍵詞部分加上顏色的顯示喔! 範例一:將 last 當中,有出現 root 的那一行就取出來; [root@www ~]# last | grep 'root' 範例二:與範例一相反,只要沒有 root 的就取出! [root@www ~]# last | grep -v 'root' 範例三:在 last 的輸出信息中,只要有 root 就取出,並且僅取第一欄 [root@www ~]# last | grep 'root' |cut -d ' ' -f1 # 在取出 root 之後,利用上個命令 cut 的處理,就能夠僅取得第一欄囉! 範例四:取出 /etc/man.config 內含 MANPATH 的那幾行 [root@www ~]# grep --color=auto 'MANPATH' /etc/man.config ....(前面省略).... MANPATH_MAP /usr/X11R6/bin /usr/X11R6/man MANPATH_MAP /usr/bin/X11 /usr/X11R6/man MANPATH_MAP /usr/bin/mh /usr/share/man # 神奇的是,如果加上 --color=auto 的選項,找到的關鍵詞部分會用特殊顏色顯示喔!
排序命令:
sort, wc, uniq
sort:
uniq: 重複的行刪除掉只顯示一個
wc:計算輸出的信息的整體數據
[root@www ~]# wc [-lwm] 選項與參數: -l :僅列出行; -w :僅列出多少字(英文單字); -m :多少字符;
雙向重導向:
tee
tee
會同時將數據流分送到文件去與屏幕 (screen);而輸出到屏幕的,其實就是 stdout
[root@www ~]# tee [-a] file 選項與參數: -a :以累加 (append) 的方式,將數據加入 file 當中! [root@www ~]# last | tee last.list | cut -d " " -f1 # 這個範例可以讓我們將 last 的輸出存一份到 last.list 文件中; [root@www ~]# ls -l /home | tee ~/homefile | more # 這個範例則是將 ls 的數據存一份到 ~/homefile ,同時屏幕也有輸出信息!
字符轉換命令:
tr, col, join, paste, expand
tr:
[root@www ~]# tr [-ds] SET1 ... 選項與參數: -d :刪除信息當中的 SET1 這個字符串; -s :取代掉重複的字符! 範例一:將 last 輸出的信息中,所有的小寫變成大寫字符: [root@www ~]# last | tr '[a-z]' '[A-Z]' # 事實上,沒有加上單引號也是可以運行的,如:『 last | tr [a-z] [A-Z] 』 範例二:將 /etc/passwd 輸出的信息中,將冒號 (:) 刪除 [root@www ~]# cat /etc/passwd | tr -d ':'
col:
[root@www ~]# col [-xb] 選項與參數: -x :將 tab 鍵轉換成對等的空格鍵 -b :在文字內有反斜槓 (/) 時,僅保留反斜槓最後接的那個字符
範例一:利用 cat -A 顯示出所有特殊按鍵,最後以 col 將 [tab] 轉成空白 [root@www ~]# cat -A /etc/man.config <==此時會看到很多 ^I 的符號,那就是 tab [root@www ~]# cat /etc/man.config | col -x | cat -A | more # 嘿嘿!如此一來, [tab] 按鍵會被取代成爲空格鍵,輸出就美觀多了!join:
- paste:
這個 paste 就要比 join 簡單多了!相對於 join 必須要比對兩個文件的數據相關性, paste 就直接『將兩行貼在一起,且中間以 [tab] 鍵隔開』而已!簡單的使用方法:
[root@www ~]# paste [-d] file1 file2 選項與參數: -d :後面可以接分隔字符。默認是以 [tab] 來分隔的! - :如果 file 部分寫成 - ,表示來自 standard input 的數據的意思。
分割命令:
split
參數代換:
xargs
關於減號
- 的用途
管線命令在 bash 的連續的處理程序中是相當重要的!另外,在 log file 的分析當中也是相當重要的一環, 所以請特別留意!另外,在管線命令當中,常常會使用到前一個命令的 stdout 作爲這次的 stdin , 某些命令需要用到文件名 (例如 tar) 來進行處理時,該 stdin 與 stdout 可以利用減號 "-" 來替代, 舉例來說:
[root@www ~]# tar -cvf - /home | tar -xvf -
上面這個例子是說:『我將 /home 裏面的文件給他打包,但打包的數據不是紀錄到文件,而是傳送到 stdout; 經過管線後,將 tar -cvf - /home 傳送給後面的 tar -xvf - 』。後面的這個 - 則是取用前一個命令的 stdout, 因此,我們就不需要使用 file 了!這是很常見的例子喔!