shell_advanced,advancedbashshell
1、輸入輸出,重新導向,管道2、<(cmd);>(cmd)3、>;<;>>;<<;>>>;<<<4、文本處理_1:cat;head;tail;cut;wc;sort;uniq;tr;tac;rev 一、輸入輸出,重新導向,管道1、Linux 程式有三個標準的輸入輸出,分別是:標準輸入,用數字0表示,預設串連到鍵盤,程式通常用來擷取使用者的輸入標準輸出,用數字1表示,預設串連到螢幕,程式通常用來輸出資訊標準錯誤,用數字2表示,預設串連到螢幕,程式通常用來輸出錯誤資訊解析: 命令 passwd 從標準輸入讀取使用者密碼,所以使用者可以用鍵盤輸入密碼命令 echo 把結果輸出到標準輸出,所以可以在螢幕上看到結果普通使用者沒有許可權查看/root 目錄,所以出錯,於是 ls 把錯誤資訊輸出到標準錯誤,也就是螢幕2、> 與 >>> 刪除原來資料,寫入新資料>> 將新資料追加到原來資料之後3、/dev/null俗稱:垃圾桶檔案# echo hello world > /dev/null --重新導向到該檔案的資料都被核心丟掉了,可以用這個特性來屏蔽某些輸出資訊# ls / /root 2> /dev/null --屏蔽掉命令的出錯資訊4、輸出重新導向使用者可以根據需要,把預設的輸入輸出的方向進行修改# ls -l > test# ls -l 1> test --兩條都是標準輸出重新導向到 test 檔案,即預設1可省略# ls /jjjj 2> test --將標準錯誤重新導向到 test 檔案# ls / /jjjj 1> stdout 2> stderr --將標準輸出與標準錯誤分別重新導向到兩個不同的檔案中# ls /jjjj / > std 2>&1 --將標準錯誤合并到標準輸出,並重新導向到一個檔案當中# ls /jjjj / &> std --結果與上條語句等價,更加簡潔# ls /jjjj / &>> std --也是將標準輸出與標準錯誤重新導向追加到一個檔案5、標準輸入重新導向 # cat 0< /etc/passwd # cat < /etc/passwd # cat /etc/passwd --cat命令的標準輸入來源於檔案 /etc/passwd 中6、管道上面所描述的重新導向,是把標準的輸入輸出串連到檔案。我們也可以把多個程式之間的標準輸入輸出進行串連,實現命令之間資料的傳遞,這種技術被形象地稱做管道,程式的輸出就像流水在管道中流通一樣,從最左邊的程式流到最右邊的程式。管道是linux shell 裡非常常見的技術,利用管道技術可以達到配合使用多個小工具,完成非常複雜而強大的功能。# cat /etc/passwd | head -n 3 --左邊的命令的標準輸出作為右邊的命令的標準輸入# cat /etc/passwd | head -n 3 | tail -n 17、標準輸入輸出的深入探討標準的輸入輸出是Linux 預設為程式建立好的三個檔案描述符,雖然大多數的程式都會使用這三個檔案描述符來作為自己的輸入輸出,但是這並非是強制性的,也就是說,程式可以不使用這三個標準的檔案描述符,而是自己開啟新的檔案描述符來使用。當程式不使用標準的輸入輸出時,這裡所使用的重新導向對其也就不起作用了。例如:passwd: 程式從標準輸入讀取使用者密碼,因此我們可以通過重新導向標準輸入來向它提供密碼ssh: 命令是用於遠程登入的程式,它讀取使用者輸入的密碼時,使用的不是標準輸入,因此我們不能通過重新導向標準輸入來向它提供密碼8、驗證進程的標準輸入輸出所串連的檔案# sleep 999 1> /tmp/good 2>&1 --在一個終端運行命令# pgrep -x sleep --在另外一個終端,找出sleep 的進程ID# lsof -anop 16715 -d 0,1,2 --查看該進程所開啟的檔案9、驗證重新導向發生的時機# vim file# cat -n file > file --期待cat 會在每一行前面加上行號,然後把結果重新導向儲存回原來的檔案file 中# cat file --為空白了原因:shell 執行命令之前,會先執行重新導向操作,在第 2 條命令中,先執行 > file,這個重新導向操作會把檔案file 的內容清空。當重新導向操作把file 檔案清空之後,再cat 該檔案,自然就看不到任何內容了$ sudo ls /root > /root/ls.log --該例子中,使用者沒有機會輸入密碼,因為重新導向操作先執行,目前使用者是普通使用者,無法在路徑 /root/ls.log 中建立檔案,shell 出錯並退出:bash: /root/ls.log: Permission denied。此時還沒有執行命令sudo,所以也就沒有機會輸入密碼 二、<(cmd);>(cmd)1、<(cmd)用進程置換的方式重新導向標準輸入2、>(cmd)用進程置換的方式重新導向標準輸出3、進程置換進程的標準輸出存到一個臨時檔案中,返回臨時檔案的路徑 <(),當需要使用程式的輸出,但是又不想產生一個中間檔案時,可以考慮使用進程置換# paste <(seq $(wc -l /etc/passwd | cut -d" " -f1)) <(awk -F: '{print $1}' /etc/passwd)# paste <(seq 26) <(awk -F: '{print $1}' /etc/passwd) --可將該兩條命令進行對比 三、>;<;>>;<<;>>>;<<<1、> --輸出重新導向,建立(存在則覆蓋)# echo 'hello world' > test -- 不存在 test 則建立,存在則覆蓋裡面內容2、< --輸入重新導向,來源於檔案# less < /etc/passwd --將 /etc/passwd 裡面的內容輸入到工具 less# cat < <(ls /) --這裡使用到命令置換# wc -l < $(echo /etc/passwd)# wc -l < <(cat /etc/passwd) --這裡使用到進程置換3、>> --重新導向到檔案,建立(存在則添加到檔案末尾)# echo 'hello george' >> george -- 不存在 george 則建立,存在則追加內容至檔案末尾4、<< --重新導向,用於Here document4.1、Here Document 是在Linux Shell 中的一種特殊的重新導向方式,它的基本的形式如下:cmd << delimiterHere Document Contentdelimiter: << delimiter --shell批量注釋Here Document Contentdelimiter作用:將兩個 delimiter 之間的內容(Here Document Content) 傳遞給 cmd 作為輸入參數 4.2、終端# cat << EOF> one> two> three> EOFEOF --只是一個標識而已,可以替換成任意的合法字元> --這個符號是終端產生的提示輸入資訊的標識符delimiter -- 一定要頂格寫,前面後面不能有任何字元,包括空格 4.3、shell# vim here.sh --註:還可在裡面使用變數#!/bin/bashcat << EOF > output.shecho "hello"echo "world"echo $1EOF# chmod a+x here.sh# ./here.sh george# cat output.sh --查看裡面內容;在這裡 $1 被展開成為了指令碼的參數注意:若不想展開這個變數,則需使用雙引號將第一個 EOF 引起來。 4.4、<<-Here Document 還有一個用法就是將 '<<' 變為 '<<-'。 使用 <<- 的唯一變化就是Here Document 的內容部分每行前面的 tab (定位字元)將會被刪除掉,這種用法是為了編寫Here Document的時候可以將內容部分進行縮排,方便閱讀代碼5、<<< --重新導向,用於Here string# wc -l <<< "$(ls -l /home)"# while read x; do echo "hello";done <<< "$(seq 5)"# bc <<< "2 ^ 10"# vim string.sh#!/bin/bashwhile read linedoif [ "${line#ftp:}" != "$line" ];thenawk -F: '{print $6}' <<< $linebreakfidone < /etc/passwd注釋:迴圈讀取/etc/passwd 檔案中的每一行,如果是ftp 使用者,就列印出其家目錄,並退出迴圈${line#ftp:}:某行開頭匹配到了 ftp: ;則只取該行未匹配部分# chmod a+x string.sh# ./string.sh 四、文本處理_1:cat;head;tail;cut;wc;sort;uniq;tr;tac;rev文本處理是每一個系統管理員都會頻繁接觸的任務,其核心內容是相關工具的使用,關鍵要點在於靈活地結合多個工具去完成任務1、cat --concatinate,把一個或者多個檔案的內容按順序連接起來,輸出到標準輸出# cat -n /etc/passwd --顯示檔案內容,並且加上行號# cat -A /etc/passwd --列印出一些不可見的字元和位置標記# cat 1.txt 2.txt > test.txt --合并檔案2、head --讀取檔案頭部# head -n 3 /etc/passwd --讀取檔案/etc/passwd 的前面三行# head -n -1 file --丟棄 file 的最後一行# head -c 3 /etc/passwd --讀取檔案/etc/passwd 的前面三個位元組# head -c -3 file --丟棄 file 的最後 3 個位元組# head -c 10m /dev/urandom > big --建立一個10M的檔案3、tail --讀取檔案尾部# tail -n 3 /etc/passwd --讀取檔案 /etc/passwd 後面三行# tail -n +28 /etc/passwd --從第28行開始讀取,直到檔案尾部;丟棄頭部的27行# tail -c 3 /etc/passwd --讀取檔案 /etc/passwd 的後面三個位元組# tail -c +28 /etc/passwd --從第28位元組開始讀取,直到檔案尾部;丟棄頭部的27位元組# tail -f /etc/passwd --追蹤檔案尾部內容的變化,常用來視察記錄檔的變化化,非常實用4、cut --功能類似於awk,但是沒有awk那麼強大和複雜,當要對資料做分列輸出時,經常使用awk,用cut的時候不多常用選項:-d --定義分隔字元-b --輸出指定位置的位元組(byte)-c --輸出指定位置的字元(character)# echo "a;b;c d;e" | cut -d ";" -f1,3,4 -- -d 定義分隔字元( 預設是 TAB );-f 定義輸出對應欄位# cat -n /etc/passwd | cut -d $'\n' -f1,3-5,7 -- 使用分行符號做分隔字元# echo 我是中國人 | cut -b1-3 -- -b 輸出指定位置的位元組(byte);一個utf8 的中文字佔用3個位元組# echo 我是中國人 | cut -c2-4 -- -c 輸出指定位置的字元(character);與-b 的區別表現在處理非英文字元時# echo 做個勇敢的中國人 | cut -b1-2,9 --會輸出一個 ”假“ 字# echo -n 做個勇敢的中國人 | xxd --會發現 1,2,9 這三個位元組為:e581 87# echo -n 假 | xxd --而 ”假“ 也是5、wc --計算資料的位元組數,字元數,單詞數,行數常用選項:-c --計算位元組數-m --計算字元數-w --計算詞數-l --計算行數# echo -n 我是中國人 | wc -c -- -c 計算位元組數,5個utf8中文佔15個位元組# echo -n 我是中國人 | wc -m -- -m 計算字元數,與-c 的區別表現在處理非英文字元時,類似於命令cut# echo -n 我是中國人 | wc -w -- -w 計算詞數,沒有分割符分開,5個中文算一個詞,這與中文所謂的“詞”是不同的# echo -n Uppercase CHINESE | wc -w --兩個詞# echo -n Uppercase CHINESE | wc -c --17個英文位元組,沒有 -n 就有18個(因為還有一個分行符號)# echo -n Uppercase CHINESE | wc -m --17個英文字元,沒有 -n 就有18個(因為還有一個分行符號)# wc -l /etc/passwd -- -l 計算行數6、sort --按行對檔案進行排序常用選項:-t --指定分割符-k --指定排序的欄位 -u --去除重複的行-n, -h --按照數值排序-r --反過來排序# cut -d ":" -f7 /etc/passwd | sort -u -- -u 去除重複行# echo -e "1\n2\n10" | sort# echo -e "1\n2\n10" | sort -n -- -n 按數值排序,不能處理K, M, G 等單位字元# ls -lh | tail -n +2 | sort -k5,5n -- -k 指定排序的欄位# ls -lh | tail -n +2 | sort -k5,5h -- -h 按照數值排序時,能處理K, M, G 等單位字元# head -4 /etc/passwd | sort -t: -k7,7 -- -t 以冒號 : 作為欄位分割符,按第7欄位排序# head -4 /etc/passwd | sort -t: -k7,7 -k3,3n --先按第7欄位排序,若第7欄位有相同的,則按第3欄位排序# echo -e "1\n2\n3" | sort -nr -- -r 對排序反轉# head -4 /etc/passwd | sort -t: -k7,7 -k3,3nr --至反轉第3欄位排序,也可同時對兩個欄位反轉7、uniq --去除連續的重複行常用選項:-c --計算重複行的數目# echo -e "1\n1\n2\n1" | uniq -- 結果中仍有兩個1,因為這兩個1是不連續的# echo -e "1\n1\n2\n1" | sort -u -- sort 去除重複則不用連續# cut -d: -f7 /etc/passwd | sort | uniq -c -- 在sort命令例子的基礎上,計算不同的登入shell出現的次數8、tr --轉換,刪除,縮減相同字元常用選項:-d --刪除,刪除匹配到的所有字母-s --縮減,縮減相同字元格式設定: tr SET1 SET2注意: 把集合1裡面的字元轉換成集合2中對應位置的字元,所以原則上兩個集合中的字元數目應該相同,不過,如果兩個集合中的字元數不相等,程式也不會出錯,請留心這種情況下的結果。要點: a、 tr 不關心兩個集合中是什麼字元,它只是簡單地把對應位置的字元逐個做替換而已、b、 tr 做的是單個字元的替換,不能替換字串# echo abc | tr a-z A-Z --把26個小寫字母轉換成相對應的大寫字母# echo abc | tr ab BA --把 a 和 b,分別轉換為 B 和 A# echo 好人做好事 | tr 好 壞 -- “好” 轉換為 “壞”# echo abcdefg | tr a-z AB --集合2較短,程式自動用集合2中最後一個字元來擴充集合2# echo abcdefg | tr a-b A-Z --集合2較長,程式自動把集合2切短# echo Abc | tr a-zA-Z A-Za-z --實現英文字母大小反轉# echo hello world | tr -d ow -- -d 刪除,匹配到的所有字母# echo 0123456789 | tr -d 13579# tr -d '\012' < /etc/passwd -- 刪除檔案/etc/passwd 中的分行符號,tr 可用八進位表示一個字元# echo aabbaacc | tr -s a -- -s,將每個連在一起的幾個 a 縮減至一個# echo aabbaacc | tr -s a A -- 集合之後再做轉換9、tac --把一個或者多個檔案的內容按順序連接起來,輸出到標準輸出,每個檔案中,內容按行號反序列印# echo -e "111111111\n2222222" > f1# echo -e "333333333\n4444444" > f2# tac f2 f110、rev --把檔案中的行左右反轉# echo -e "1234567\nabcdefg" > test# rev test 五、擴充1、cat,md5sum# echo file1 > file1# echo file2 > file2 --建立兩個檔案# md5sum file1 file2 --對比他們的 md5 值是否相同# head -c 10m /dev/urandom > bigfile --使用隨機裝置建立一個 10M 的檔案# head -c 3m bigfile > file1 --將前 3M 資料匯入 file1# tail -c 4m bigfile > file3 --將後 3M 資料匯入 file3# head -c 6m bigfile | tail -c 3m > file2 --將中間 4M 資料匯入 file2# ls -lh file*# cat file1 file2 file3 > newbigfile --使用 cat 將三個檔案合并到一個新大檔案中# md5sum newbigfile bigfile --在用命令比較舊大檔案與新大檔案的 md5sum 值