Linux 之 Bash -- 管線命令

聲明: 我覺得今天的這篇文章就像一篇“工具”文而且很雞肋:歸納一些常用的管線命令和應用參數。適合有操作需求時,來查找能夠幫忙解決問題的指令和參數~

學習管線命令之前要先了解管道符|,因爲管線命令使用的是|這個界定符號,它和使用;的連續下達命令“很像”(關於連續命令符號“;”,Linux 之 Bash -- 數據流重導向裏面剛學過,這裏不再提啦~)。爲了理解“|”,我們來舉個例子:
我想看一下 /etc這個目錄下的文件列表,但是這個目錄裏的東西實在太多了,直接 ls -l /etc打印到屏幕上滿屏都是,往回翻操作記錄都麻煩,所以可以使用ls -l /etc | less,這樣ls指令輸出後的內容就能夠被less讀取,並且利用less的功能,我們就能夠前後翻動相關的信息了。這是ls -l /etc ; less達不到的效果,因爲;只起到下達命令的作用,而|卻起到傳遞標準輸出STDOUT的作用,這是本質的區別。整體的管線命令可以用這個圖表表示:


使用時有兩個注意點:

  • 管線命令僅會處理 standard output,對於 standard error output 會予以忽略
  • 管線命令必須要能夠接受來自前一個指令的數據成爲 standard input 繼續處理才行
    例如 ls,cp,mv這些不會接受stdin的命令,是不適合放在管道符|後面的

1.擷(xie)取命令: cut,grep

用過cut的夥伴都知道,cut可以提取列,可是實際上,它和grep一樣都是針對文本“一行一行”來分析的,以cut -f 3 filename爲例:cut文本第一行的第3段數據;cut文本第二行的第3段數據....直到文本的最後一行。最終,組成一列數據輸出出來。

1.1 cut

詳細聊聊cut的應用

  • -d 後面接分隔字符,與-f一起使用
    eg: cut -d ':' -f 3,5 linux.txt 翻譯成人話就是 linux.txt以“:”爲分隔字符,幫我把第3段和第5段切出來
  • -f 後面接數字,取出第幾段的意思
  • -c 後面接數字
    以字符(characters)的單位取出固定字符區間
    eg: cut -c 1-8 linux.txt 翻譯成人話 幫我把linux.txt中的,每一行的,第1-8個字符切出來(如果是8-,意即把第8個之後的字符都切出來)

1.2 grep

grep同樣是一行一行得分析,它的做事風格很豪爽:如果當中有我想要的信息,就把這一整行都拽出來
grep支持的語法很多,還支持 正規表示法 ,可惜panda還沒把正規表示法學通,在這裏就只簡單介紹幾個參數,等到後面再及時更新

  • -c 計算“搜尋字符串”的次數
    eg: grep -c time linux.txt 翻譯成人話 計算time在linux.txt中出現的次數
  • -i 忽略大小寫來擷取文本行
    eg:grep -i AB linux.txt 翻譯成人話 把linux.txt文本中含有"ab or AB or Ab or aB"的文本行拽出來
  • -n 順便輸出行號
  • -v 反向選擇,顯示沒有“搜索字符串”內容的那一行

2.排序命令 sort,wc,uniq

2.1 sort

sort的大特點:可以依據不同的數據型態來排序

  • -f 忽略大小寫的差異
  • -b 忽略最前面的空格符部分
  • -M 以月份的名字來排序
  • -n 使用純數字進行排序(默認是以文字型態來排序的)
  • -r 反向排序
  • -u 相同的數據中,僅出現一行代表(uniq)
  • -t 指定分隔符(預設是用tab鍵) 和 cut 中的-d參數作用類似
  • -k 以哪個區間排序
    eg: sort -k 3 linux.txt 以linux.txt中的第3列進行排序

2.2 uniq

用於排序完成後,將重複的資料僅列出一個顯示,它的一些參數:

  • -i 忽略大小寫字符的不同
  • -c 進行計數

2.3 wc 統計行數、字數、字符數

  • -l 僅列出行
  • -w 僅列出多少字(英文單字)
  • -m 多少字符

3.雙向重導向 tee

tee的功能其實很簡單,可以讓standard output轉存一份到文件內並將同樣的數據繼續送到屏幕去處理


舉個例子來認識它:
ls -l | tee list.txt | less 翻譯成人話:查看當前目錄並且將目錄內容保存到 list.txt中
看到了吧,這裏tee把standard ourtput做了雙向輸出:一個走向 list.txt;一個走向 屏幕,不過我這裏用less來查看信息
除此之外,記憶一個tee的參數:

  • -a 以累加的方式,將數據加入file當中(類似>>)

4.字符轉換命令:tr,col,join,paste,expand

4.1 tr(刪除或替換文字訊息)

刪除一段訊息中的文字;或者進行文字訊息的替換

注意:tr只能從標準輸入中讀取數據,因此使用tr時,
1.要麼通過<將輸入文件重定向到標準輸入;

2.要麼通過管道符|讀入數據

  • tr '[a-z]' '[A-Z]' 將所有的小寫變成大寫
    eg: tr '[a-z]' '[A-Z]' < list.txt 將list.txt 中的所有小寫字母轉換成大寫輸出到屏幕
  • -d 刪除訊息當中的字符串
    eg: cat /etc/passwd | tr -d ':' /etc/passwd 輸出的訊息中,將“:”刪除
  • -s 取代掉重複的字符

4.2 col(用對等的空格鍵取代tab鍵)

最常用的操作:通過使用參數-x,將[tab]按鍵取代成爲對應的 相同長度的 空格鍵
eg:cat -A list.txt (如果list.txt 中有tab鍵,就會看到很多^I的符號;cat -A可以顯示出所有的特殊按鍵)
再試試cat list.txt | col -x | cat -A 這樣打印到屏幕的輸出就美觀多了
不要光說不做哦~just do it ~

4.3 join(根據相關性合併文件)

join這個小命令只能處理2個文件之間的數據:兩個文件當中,有“相同數據”的那一行,纔將他們加在一起
例如 /etc/passwd 和 /etc/shadow這兩個文件(先看他們的文本特點):


可以看到,這兩個文本的分隔符都是:,同時第一個字段的內容都相同(都是 root,bin,daemon),如果我們想要把兩個文本中不同的數據合在一起,就可以使用join將他們變成這個樣子:join -t ':' /etc/passwd /etc/shadow | head -n 3

認識join的一些參數:join [-ti12] file1 file2

  • -t: 用來指定分隔符
    👆 join -t ':' /etc/passwd /etc/shadow | head -n 3中就是讓兩個文件合併後以':'分隔。如果不設置的話,默認以空格分隔數據
  • -i : 忽略大小寫的差異
  • -1 代表第一個文件 -2 代表第二個文件
    這兩個數字分別指代對應文件要用哪個字段來分析進行整合
    eg:join -1 2 a.txt -2 3 b.txt 翻譯成人話 將a.txt的第2個字段和b.txt的第3個字段整合在一起

注意:插播一下使用join時的注意點

1.需要處理的文件以防順序錯亂,最好排序並去重後再join;
2.指定要整合的字段要相同啊!

而剛開始瞭解join時,沒有數字參數的這個指令是怎麼執行的?join -t ':' /etc/passwd /etc/shadow | head -n 3
實際上,👆它只是進行了參數的省略而已,linux默認以兩個文件的第1個字段進行分析和整合,完整的它應該是這個樣子join -t ':' -1 1 /etc/passwd -2 1 /etc/shadow | head -n 3
怎麼樣?是不是有點頭暈?哈哈,記住就好啦~
總之,join在處理兩個相關的數據文件時是非常有幫助的,例如/etc/passwd和/etc/shadow以賬號爲相關性,而/etc/passwd和/ec/group以所謂的GID(賬號的數字定義)爲相關性,通過join可以把這些有用的數據放在一起。

4.4 paste(簡單粗暴得合併文件)

和join作用類似,也是將兩個文件的數據貼在一起,但是它的方式簡單粗暴,不會去比較內容是否相關,而是直接將行號相同的字段拼在一起,默認以tab鍵分隔。
工作模式 paste [-d] file1 file2

  • -d 後面可以接分隔字符,預設是tab鍵
    eg: paste /etc/passwd /etc/shadow
  • - 如果file部分寫成-,表示來自standard input的資料的意思(以後用到再詳細解釋)

4.5 expand(用空格取代tab鍵)

還記得上面提到的col -x嗎,它可以將tab鍵取代爲相同長度的空格鍵。expand和它作用類似,不過expand可以自由設定tab鍵取代成空格鍵的個數,所以功能是比col -x更強大的。
常見的工作模式 expand [-t] file

  • -t後面可以接數字
    eg: expand -t 6 a.txt | cat -A 將a.txt中的tab鍵以1:6的個數比例轉換成空格鍵,並且打印到屏幕(cat -A看一下文件內的所有特殊符號)

小插曲:** 如果我想讓空格鍵轉成tab鍵怎麼辦? **
答案:使用 unexpand

  • -a 除了單詞前作爲單詞分隔的空格外,所有空格都會被轉換
  • --first-only 僅轉換每行開頭的空格
  • -t 指定一個tab鍵佔幾個字符位(默認8)

5. 分區命令:split

split可以根據文件大小或行數來分區,從而將大文件分成小文件。
(在我們常用的windows裏面可是個大問題啊,而進入linux,我們可以很方便得使用split啦~)
常用工作模式: split [-bl] file PREFIX
常用選項和參數

  • -b 後面可接欲分區成的文件大小(可加單位,eg: b,k,m等)
  • -l 以行數來進行分區
    PREFIX 代表前導符的意思,可作爲分區文件的前導文字
    eg:
  • 按文件大小split
    如果 a.txt 是一個800+kb的大文件,可以通過split分成3個最大爲300kb 的文件。 指令: split -b 300k a.txt
  • 按文件行數split
    如果 a.txt 是一個100+ 行的大文件,可以通過split分成6個最大爲20行的文件。 指令 : split -l 20 a.txt

6.參數代換:xargs

xargs 可以用來產生某個指令的參數,可讀入stdin的數據,並且以空格符或斷行字符作爲分辨,將stdin的資料分隔成arguments(參數)。

xargs聽起來很嚇人,難理解也是因爲實踐與想象有差距。如果學着應用它,就會發現,它其實也是很簡單的一個命令,don't panic~
常見工作模式: xargs [-0epn] command
選項與參數:

  • -0 (數字0不是字母O啊~)
    如果輸入的stdin含有特殊字符,例如. \ \.空格鍵等字符時,這個-0參數可以將他還原成一般字符。這個參數可以用於特殊狀態。
  • -e 這個是EOF (end of file) 的意思,後面可以接一個字符串,當xargs分析到這個字符串時,就會停止繼續工作。
  • -p 在執行每個指令的argument時,都會詢問使用者的意思
  • -n 後面接次數,每次command指令執行時,要使用幾個參數的意思
實踐前熱身(可以試着在自己的集羣上操作)

下面分幾步介紹id,同時襯托一下xargs存在的“魅力”!
id 指令可以查詢用戶的UID/GID等信息 eg: id root

  • step 1 認識id只接受一個參數的侷限性
    id $(cut -d ':' -f 1 /etc/passwd | head -n 3)
    翻譯成人話: 將/etc/passwd中的第一列的前三行取出來,並且使用id指令查看信息
    這裏通過$(cut -d ':' -f 1 /etc/passwd | head -n 3)預先取得了參數,但是因爲id只能接受一個參數,因此它會在linux系統裏報錯。
    -step 2 認識 id並不是管線命令的侷限性
    cut -d ':' -f 1 /etc/passwd | head -n 3 | id
    最終你會發現,你查了自己!因爲id不是管線命令,它是沒有辦法接收|前面的信息的。因此cut -d ':' -f 1 /etc/passwd | head -n 3 | id 的執行效果 就等於 直接在linux命令行中輸入id 所執行的結果。

這可腫麼辦? xargs來了就有了辦法~

  • xargs -n
    cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id 就可以順利得獲得相應用戶的詳細信息,把它翻譯成人話就是:將/etc/passwd的第一列的前三行提出來然後通過xargs將此三行內容轉換成指令id的參數(考慮到id只能一個一個得接收參數,因此使用了-n 1使3個參數一個一個得傳遞到達)
  • xargs -p
    cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -p -n 1 id 這裏增加了-p選項,則在使用過程中,被詢問到每個指令是否執行!
  • xargs -e
    cut -d ':' -f 1 /etc/passwd | xargs -e'sync' -n 1 id
    在我們下達 -e'sync'後,在分析到sync這個字符串時,後面的stdin內容就會被xargs捨棄掉了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章