shell基礎知識8-xargs命令

簡介

xargs 命令應該緊跟在管道操做符以後。它使用標準輸入做爲主要的數據源,將從 stdin 中
讀取的數據做爲指定命令的參數並執行該命令。node

將多行輸入轉換成單行輸出
[root@dns-node2 ~]# cat example.txt | xargs
1 2 3 4 5 6 7 8 9 10 11 12 13
將單行輸入轉換成多行輸出。

-n 指定每行個數shell

[root@dns-node2 ~]# cat example.txt | xargs -n 3
1 2 3
4 5 6
7 8 9
10 11 12
13
指定分隔符

xargs 命令接受來自 stdin 的輸入,將數據解析成單個元素,而後調用指定命令並將這些元
素做爲該命令的參數。 xargs 默認使用空白字符分割輸入並執行/ bin/echo 。
若是文件或目錄名中包含空格(甚至是換行)的話,使用空白字符來分割輸入就會出現問題。
好比My Documents目錄就會被解析成兩個元素: My 和 Documents ,而這二者均不存在。
天無絕人之路,此次也不例外。
咱們能夠定義一個用來分隔參數的分隔符。 -d 選項能夠爲輸入數據指定自定義的分隔符命令行

[root@dns-node2 ~]# echo "a1xb2xc3xd4" | xargs -d x
a1 b2 c3 d4

xargs 命令能夠同 find 命令很好地結合在一塊兒。 find 的輸出能夠經過管道傳給 xargs, 由後
者執行 -exec 選項所沒法處理的複雜操做。若是文件系統的有些文件名中包含空格, find 命令的
-print0 選項可使用 0 (NULL)來分隔查找到的元素,而後再用 xargs 對應的 -0 選項進行解
析。code

[root@dns-node2 tmp]# find ./ -iname "*.sh" |xargs -0 grep sleep -L
grep: ./testSet.sh
讀取stdin,爲命令傳入格式化參數

先說下咱們的需求:
1 咱們有參數保存在參數文件裏面,咱們要從這個參數文件裏面讀取參數而且提供給某個命令使用,那咱們可使用xargs來結合使用
首先查看參數列表:dns

[root@dns-node2 tmp]# cat args.txt
timeout 3
interval 3
hostname 1.1.1.1

那下一步就是把這些參數都傳給腳本字符串

[root@dns-node2 tmp]# cat args.txt | xargs -n 2  ./testPrint.sh

經過-n 參數來控制傳多少個參數給testPring.sh ,若是不寫-n 那麼就把全部參數傳入給testPrint.sh ,不然就由-n來指定參數個數。-n 1就是傳一個參數。cmd

2 第二種狀況是假設咱們腳本須要2個參數,其中有一個參數時固定的,另一個參數可變的。那怎麼保持固定參數不變呢?經過-I參數來指定替換字符串。這個字符串會在 xargs 解析輸入時被參
數替換掉。若是將 -I 與 xargs 結合使用,對於每個參數,指定命令只會執行一次,此時若是結合-n使用的話,-n是無效的test

[root@dns-node2 tmp]# cat args.txt | xargs -I {} ./testPrint.sh {} fixedArgs
timeout 3 fixedArgs#
interval 3 fixedArgs#
hostname 1.1.1.1 fixedArgs#

-I {} 指定了替換字符串。爲該命令提供的各個參數會經過 stdin 讀取並依次替換掉字符串 {} 。file

使用 -I 的時候,命令以循環的方式執行。若是有3個參數,那麼命令就會連
同 {} 一塊兒被執行3次。 {} 會在每次執行中被替換爲相應的參數。循環

結合find使用xargs

使用 find 命令的 -print0 選項生成以空字符( '\0' )做爲分隔符的輸出,而後將其做爲
xargs 命令的輸入
若是不使用-print0的話而在xargs 使用-0參數的話,由於二者發生矛盾了,你們能夠看到下面第一條命令報錯了

[root@dns-node2 tmp]# find . -type f -name "*.txt" | xargs -0 ls -l
ls: cannot access ./output.txt
./args.txt
: No such file or directory  # 報錯了?,沒有使用-print0
[root@dns-node2 tmp]# find . -type f -name "*.txt" -print0 | xargs -0 ls -l
-rw-r--r-- 1 root root 38 Sep 16 22:49 ./args.txt
-rw-r--r-- 1 root root  8 Sep  4 22:28 ./output.txt
結合stdin ,巧妙運用while語句和子shell

xargs 會將參數放置在指定命令的尾部,所以沒法爲多組命令提供參數。咱們能夠經過建立子shell來處理這種複雜狀況。子shell利用while循環讀取參數並執行命令,有2種方法,就像這樣:

1 方法1

[root@dns-node2 tmp]# ls *.sh | (while read arg; do cat $arg; done)

2 方法2

[root@dns-node2 tmp]# ls *.sh | xargs -I a cat a

在 while 循環中,能夠將 cat $arg 替換成任意數量的命令,這樣咱們就能夠對同一個參數
執行多條命令。也能夠不借助管道將輸出傳遞給其餘命令。這種利用 () 建立子shell的技巧能夠應
用於各類問題場景。子shell操做符內部的多條命令在執行時就像一個總體,所以:

$ cmd0 | ( cmd1;cmd2;cmd3) | cmd4

若是 cmd1 是 cd / ,那麼就會改變子shell工做目錄,然而這種改變僅侷限於該子shell內部。
cmd4 則不受工做目錄變化的影響。

shell的 -c 選項能夠調用子shell來執行命令行腳本。它能夠與 xargs 結合解決屢次替換的問
題。下列命令找出了全部的C文件並顯示出每一個文件的名字,文件名前會加上一個換行符( -e 選
項容許進行轉義替換)。在文件名以後是該文件中含有main的全部行:

[root@dns-node2 tmp]# ls *.sh | xargs -I {}  sh -c "echo -ne '\n {}: ';grep sleep {}"
相關文章
相關標籤/搜索