1、輸入輸出,重定向,管道 2、<(cmd);>(cmd) 3、>;<;>>;<<;>>>;<<< 4、文本處理_1:cat;head;tail;cut;wc;sort;uniq;tr;tac;rev 一、輸入輸出,重定向,管道 1、Linux 程式有三個標準的輸入輸出,分別是: 標準輸入,用數字0 ...
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 1 7、標準輸入輸出的深入探討 標準的輸入輸出是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 document 4.1、Here Document 是在Linux Shell 中的一種特殊的重定向方式,它的基本的形式如下: cmd << delimiter Here Document Content delimiter : << delimiter --shell批量註釋 Here Document Content delimiter 作用:將兩個 delimiter 之間的內容(Here Document Content) 傳遞給 cmd 作為輸入參數 4.2、終端 # cat << EOF > one > two > three > EOF EOF --只是一個標識而已,可以替換成任意的合法字元 > --這個符號是終端產生的提示輸入信息的標識符 delimiter -- 一定要頂格寫,前面後面不能有任何字元,包括空格 4.3、shell # vim here.sh --註:還可在裡面使用變數 #!/bin/bash cat << EOF > output.sh echo "hello" echo "world" echo $1 EOF # 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/bash while read line do if [ "${line#ftp:}" != "$line" ];then awk -F: '{print $6}' <<< $line break fi done < /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 f1 10、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 值