1. 程式人生 > >鳥哥的Linux私房菜讀書筆記--管線命令pipe

鳥哥的Linux私房菜讀書筆記--管線命令pipe

注意:管線命令與連續下達命令是不一致的

管線命令只能處理由前一個指令傳來的正確資訊,也就是standard output資訊,對於standard error並沒有直接處理的能力。

每個管線的後面接的第一個資料一定是指令,該指令必須能夠接受standard input的資料,這樣的指令才可以是管線命令,例如less、more、head、tail都是可以接受standard input的管線命令,例如ls、cp、mv等不適管線命令,因為ls、cp、mv等並不會接受standard  input的資料。

      注意:(1)管線命令僅會處理standard  output,對於standard error output會予以忽略

                 (2)管線命令必須要能夠接受 來自前一個指令的資料成為standard input繼續處理才行

如果我們需要硬讓standard error可以被管線命令所用,通過資料流重導向讓2>&1加入指令中就可以讓2>變成1>

1、摘取命令

<1>cut

    [[email protected] ~]$ cut -d'分隔字元' -f fields <==用於有特定分隔字元     [[email protected] ~]$ cut -c 字元區間 <==用於排列整齊的訊息         選項與引數:             -d :後面接分隔字元。與 -f 一起使用;             -f :依據 -d 的分隔字元將一段訊息分割槽成為數段,用 -f 取出第幾段的意思;             -c :以字元 (characters) 的單位取出固定字元區間;

    範例二:將 export 輸出的訊息,取得第 12 字元以後的所有字串         [[email protected] ~]$ export             declare -x HISTCONTROL="ignoredups"             declare -x HISTSIZE="1000"             declare -x HOME="/home/dmtsai"             declare -x HOSTNAME="study.centos.vbird"     # 注意看,每個資料都是排列整齊的輸出!如果我們不想要『 declare -x 』時,就得這麼做:         [

[email protected] ~]$ export | cut -c 12-             HISTCONTROL="ignoredups"             HISTSIZE="1000"             HOME="/home/dmtsai"             HOSTNAME="study.centos.vbird"     # 還可以指定某個範圍的值,例如第 12-20 的字元,就是 cut -c 12-20 等等! <2>grep

cut指令是取出某部分我們想要的,而grep是分析一行資訊

    [[email protected] ~]$ grep [-acinv] [--color=auto] '搜尋字串' filename        選項與引數:            -a :將 binary 檔案以 text 檔案的方式搜尋資料             -c :計算找到 '搜尋字串' 的次數             -i :忽略大小寫的不同,所以大小寫視為相同             -n :順便輸出行號             -v :反向選擇,亦即顯示出沒有 '搜尋字串' 內容的那一行!             --color=auto :可以將找到的關鍵詞部分加上顏色的顯示喔!     範例一:將 last 當中,有出現 root 的那一行就取出來;         [[email protected] ~]$ last | grep 'root'     範例二:與範例一相反,只要沒有 root 的就取出!         [[email protected] ~]$ last | grep -v 'root'     範例三:在 last 的輸出訊息中,只要有 root 就取出,並且僅取第一欄         [[email protected] ~]$ last | grep 'root' |cut -d ' ' -f1     # 在取出 root 之後,利用上個指令 cut 的處理,就能夠僅取得第一欄囉!     範例四:取出 /etc/man_db.conf 內含 MANPATH 的那幾行         [[email protected] ~]$ grep --color=auto 'MANPATH' /etc/man_db.conf             MANPATH_MAP /usr/games /usr/share/man             MANPATH_MAP /opt/bin /opt/man             MANPATH_MAP /opt/sbin /opt/man     # 神奇的是,如果加上 --color=auto 的選項,找到的關鍵詞部分會用特殊顏色顯示喔!

2、排序命令:sort、wc、uniq

<1>sort    ##按照一定方式將輸出排序

    [[email protected] ~]$ sort [-fbMnrtuk] [file or stdin]         選項與引數:             -f :忽略大小寫的差異,例如 A 與 a 視為編碼相同;             -b :忽略最前面的空格符部分;             -M :以月份的名字來排序,例如 JAN, DEC 等等的排序方法;             -n :使用『純數字』進行排序(預設是以文字型態來排序的);             -r :反向排序;             -u :就是 uniq ,相同的資料中,僅出現一行代表;             -t :分隔符,預設是用 [tab] 鍵來分隔;             -k :以那個區間 (field) 來進行排序的意思     範例一:個人賬號都記錄在 /etc/passwd 下,請將賬號進行排序。         [[email protected] ~]$ cat /etc/passwd | sort             abrt:x:173:173::/etc/abrt:/sbin/nologin             adm:x:3:4:adm:/var/adm:/sbin/nologin             alex:x:1001:1002::/home/alex:/bin/bash     # 鳥哥省略很多的輸出~由上面的資料看起來, sort 是預設『以第一個』資料來排序,而且預設是以『文字』型態來排序         的喔!所以由 a 開始排到最後囉!

<2>uniq    ##將重複的資料僅列出一個顯示

    [[email protected] ~]$ uniq [-ic]         選項與引數:             -i :忽略大小寫字元的不同;             -c :進行計數     範例一:使用 last 將賬號列出,僅取出賬號欄,進行排序後僅取出一位;         [[email protected] ~]$ last | cut -d ' ' -f1 | sort | uniq     範例二:承上題,如果我還想要知道每個人的登入總次數呢?         [[email protected] ~]$ last | cut -d ' ' -f1 | sort | uniq -c              1              6 (unknown              47 dmtsai              4 reboot              7 root              1 wtmp     # 從上面的結果可以發現 reboot 有 4 次, root 登入則有 7 次!大部分是以 dmtsai 來操作! wtmp 與第一行的空白都是             last 的預設字元,那兩個可以忽略的!

<3>wc    ##對檔案內容進行統計

    命令:$ wc  [-lwm]                                                                                                                                                                            選項與引數:             -l :僅列出行;             -w :僅列出多少字(英文單字);             -m :多少字元;     範例一:那個 /etc/man_db.conf 裡面到底有多少相關字、行、字元數?         [[email protected] ~]$ cat /etc/man_db.conf | wc               131 723 5171     # 輸出的三個數字中,分別代表: 『行、字數、字元數』     範例二:我知道使用 last 可以輸出登入者,但是 last 最後兩行並非賬號內容,那麼請問,我該如何以一行指令串取得登入                    系統的總人次?         [[email protected] ~]$ last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' |  grep -v 'unknown' |wc -l      # 由於 last 會輸出空白行, wtmp, unknown, reboot 等無關賬號登入的資訊,因此,我利用grep 取出非空白行,以及去除上         述關鍵詞那幾行,再計算行數,就能夠了解囉!

3、雙向重導向(同時將資料流傳遞給檔案和螢幕)

[[email protected] ~]$  tee  [-a]  file     選項與引數:         -a :以累加 (append) 的方式,將資料加入 file 當中!

用途:使standard output 轉存到檔案中,並將檔案內的資料顯示到螢幕上,可以使我們分析同時記錄資料,還可以作為處理資料的中間暫存檔使用。

4、字元轉換命令:tr、col、join、paste、expand

<1>tr    刪除或替換文字

    [[email protected] ~]$ tr [-ds] SET1 ...         選項與引數:             -d :刪除訊息當中的 SET1 這個字串;             -s :取代掉重複的字元!     範例一:將 last 輸出的訊息中,所有的小寫變成大寫字元:         [[email protected] ~]$ last | tr '[a-z]' '[A-Z]'     # 事實上,沒有加上單引號也是可以執行的,如:『 last | tr [a-z] [A-Z] 』     範例二:將 /etc/passwd 輸出的訊息中,將冒號 (:) 刪除         [[email protected] ~]$ cat /etc/passwd | tr -d ':'

<2>col    ##將tab鍵轉換為對等的空格鍵

[[email protected] ~]$ col [-xb]     選項與引數:         -x :將 tab 鍵轉換成對等的空格鍵     範例一:利用 cat -A 顯示出所有特殊按鍵,最後以 col 將 [tab] 轉成空白         [[email protected] ~]$ cat -A /etc/man_db.conf <==此時會看到很多 ^I 的符號,那就是 tab         [[email protected] ~]$ cat /etc/man_db.conf | col -x | cat -A | more     # 嘿嘿!如此一來, [tab] 按鍵會被取代成為空格鍵,輸出就美觀多了!

<3>join    ##處理兩個檔案之間的資料,對有相同資料的那一行,將他們加在一起

    [[email protected] ~]$  join  [-ti12]  file1  file2         選項與引數:             -t :join 預設以空格符分隔資料,並且比對『第一個欄位』的資料,如果兩個檔案相同,則將兩筆資料聯成一行,且                      第一個欄位放在第一個!             -i :忽略大小寫的差異;             -1 :這個是數字的 1 ,代表『第一個檔案要用那個欄位來分析』的意思;             -2 :代表『第二個檔案要用那個欄位來分析』的意思。     範例二:我們知道 /etc/passwd 第四個欄位是 GID , GID 記錄在/etc/group 當中的第三個欄位,請問如何兩個檔案整合?         [[email protected] ~]# head -n 3 /etc/passwd /etc/group             ==> /etc/passwd <==             root:x:0:0:root:/root:/bin/bash             bin:x:1:1:bin:/bin:/sbin/nologin             daemon:x:2:2:daemon:/sbin:/sbin/nologin             ==> /etc/group <==             root:x:0:             bin:x:1:             daemon:x:2:     # 從上面可以看到,確實有相同的部分喔!趕緊來整合一下!         [[email protected] ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3             0:root:x:0:root:/root:/bin/bash:root:x:             1:bin:x:1:bin:/bin:/sbin/nologin:bin:x:             2:daemon:x:2:daemon:/sbin:/sbin/nologin:daemon:x:     # 同樣的,相同的欄位部分被移動到最前面了!所以第二個檔案的內容就沒再顯示。 注意:在使用join之前,需要對所處理的問津先進行排序(sort)

<4>paste    ##paste直接將兩行貼在一起,且中間以tab鍵隔開

    [[email protected] ~]$ paste [-d] file1 file2         選項與引數:             -d :後面可以接分隔字元。預設是以 [tab] 來分隔的!             - :如果 file 部分寫成 - ,表示來自 standard input 的資料的意思。

<5>expand    ##將tab鍵轉換為空格鍵

    [[email protected] ~]$ expand [-t] file         選項與引數:             -t :後面可以接數字。一般來說,一個 tab 按鍵可以用 8 個空格鍵取代。我們也可以自行定義一個 [tab] 按鍵代表多少                    個字元呢!     範例三:承上,我將 [tab] 按鍵設定成 6 個字元的話?         [[email protected] ~]$ grep '^MANPATH' /etc/man_db.conf | head -n 3 | expand -t 6 - | cat -A             MANPATH_MAP/bin/usr/share/man$             MANPATH_MAP/usr/bin/usr/share/man$             MANPATH_MAP/sbin/usr/share/man$    ##下劃線表示空格

5、分割槽命令:split

    [[email protected] ~]$ split [-bl] file PREFIX         選項與引數:             -b :後面可接欲分割槽成的檔案大小,可加單位,例如 b, k, m 等;             -l :以行數來進行分割槽。             PREFIX :代表前導符的意思,可作為分割槽檔案的前導文字。     範例一:我的 /etc/services 有六百多 K,若想要分成 300K 一個檔案時?         [[email protected] ~]$ cd /tmp; split -b 300k /etc/services services         [[email protected] tmp]$ ll -k services*             -rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesaa             -rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesab             -rw-rw-r--. 1 dmtsai dmtsai 55893 Jul 9 22:52 servicesac     # 那個檔名可以隨意取,只要寫上前導文字,小檔案就會以xxxaa, xxxab, xxxac 等方式來建立小檔案的!     範例二:如何將上面的三個小檔案合成一個檔案,檔名為 servicesback         [[email protected] tmp]$ cat services* >> servicesback        # 資料流重導向

6、引數代換:xargs

        x指乘號,args指arguments(引數),即產生某個指令的引數,xargs可以讀入stdin的資料,並且以空格或斷行字元作為分別,將stdin的資料分隔稱為arguments

    [[email protected] ~]$ xargs [-0epn] command         選項與引數:             -0 :如果輸入的 stdin 含有特殊字元,例如 `, \, 空格鍵等等字元時,這個 -0 引數可以將他還原成一般字元。             -e :這個是 EOF (end of file) 的意思。後面可以接一個字串,當 xargs 分析到這個字串時,就會停止繼續工作!             -p :在執行每個指令的 argument 時,都會詢問使用者的意思;             -n :後面接次數,每次 command 指令執行時,要使用幾個引數的意思。當 xargs 後面沒有接任何的指令時,預設是                      以 echo 來進行輸出喔!     範例一:將 /etc/passwd 內的第一欄取出,僅取三行,使用 id 這個指令將每個賬號內容秀出來         [[email protected] ~]$ id root             uid=0(root) gid=0(root) groups=0(root) # 這個 id 指令可以查詢使用者的 UID/GID 等資訊         [[email protected] ~]$ id $(cut -d ':' -f 1 /etc/passwd | head -n 3)     # 雖然使用 $(cmd) 可以預先取得引數,但可惜的是, id 這個指令『僅』能接受一個引數而已!     # 所以上述的這個指令執行會出現錯誤!根本不會顯示使用者的 ID 啊!         [[email protected] ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | id             uid=1000(dmtsai) gid=1000(dmtsai) groups=1000(dmtsai),10(wheel) # 我不是要查自己啊!     # 因為 id 並不是管線命令,因此在上面這個指令執行後,前面的東西通通不見!只會執行 id!         [[email protected] ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs id     # 依舊會出現錯誤!這是因為 xargs 一口氣將全部的資料通通丟給 id 處理~但 id 就接受 1 個啊最多!         [[email protected] ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id             uid=0(root) gid=0(root) groups=0(root)             uid=1(bin) gid=1(bin) groups=1(bin)             uid=2(daemon) gid=2(daemon) groups=2(daemon)     # 透過 -n 來處理,一次給予一個引數,因此上述的結果就 OK 正常的顯示囉!     範例二:同上,但是每次執行 id 時,都要詢問使用者是否動作?         [[email protected] ~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id            id root ?...y             uid=0(root) gid=0(root) groups=0(root)             id bin ?...y     #  -p 的選項可以讓使用者的使用過程中,被詢問到每個指令是否執行!     範例三:將所有的 /etc/passwd 內的賬號都以 id 查閱,但查到 sync 就結束指令串         [[email protected] ~]$ cut -d ':' -f 1 /etc/passwd | xargs -e'sync' -n 1 id     # 仔細與上面的案例做比較。也同時注意,那個 -e'sync' 是連在一起的,中間沒有空格鍵。上例中,第六個引數是 sync ,當下達 -e'sync' 後,則分析到 sync 這個字串時,後面的其他 stdin 的內容就會被 xargs 捨棄掉了!         使用 xargs 的原因是, 很多指令並不支援管線命令,因此我們可以透過 xargs 來提供該指令引用 standard input 之用!舉例來說,我們使用如下的範例來說明:     範例四:找出 /usr/sbin 底下具有特殊許可權的檔名,並使用 ls -l 列出詳細屬性         [[email protected] ~]$ find /usr/sbin -perm /7000 | xargs ls -l             -rwx--s--x. 1 root lock 11208 Jun 10 2014 /usr/sbin/lockdev             -rwsr-xr-x. 1 root root 113400 Mar 6 12:17 /usr/sbin/mount.nfs             -rwxr-sr-x. 1 root root 11208 Mar 6 11:05 /usr/sbin/netreport     # 聰明的讀者應該會想到使用『 ls -l $(find /usr/sbin -perm /7000) 』來處理這個範例!

7、減號- 的用途

某些檔名需要用到檔名來進行處理,該stdin與是stdout可以利用減號-來替代。