關于Linux下xargs命令詳解以及xargs與管道的區別

為什么要用xargs,問題的來源

在工作中經常會接觸到xargs命令,特別是在別人寫的腳本里面也經常會遇到,但是卻很容易與管道搞混淆,本篇會詳細講解到底什么是xargs命令,為什么要用xargs命令以及與管道的區別。為什么要用xargs呢,我們知道,linux命令可以從兩個地方讀取要處理的內容,一個是通過命令行參數,一個是標準輸入。例如cat、grep就是這樣的命令,舉個例子:

echo?'main'?|?cat?test.cpp

這種情況下cat會輸出test.cpp的內容,而不是’main’linux,如果test.cpp不存在則cat命令報告該文件不存在,并不會嘗試從標準輸入中讀取。echo ‘main’ | 會通過管道將 echo 的標準輸出(也就是字符串’main’)導入到 cat 的標準輸入,也就是說此時cat的標準輸入中是有內容的,其內容就是字符串’main’但是上面的內容中cat不會從它的標準輸入中讀入要處理的內容。(注:標準輸入是有一個緩沖區的,就像我們在程序中使用scanflinux從標準輸入中讀取一樣,實際上是從標準輸入的緩沖區中讀取的)。其實基本上linux的命令中很多的命令的設計是先從命令行參數中獲取參數,然后從標準輸入中讀取,反映在程序上,命令行參數是通過main函數的 int main(int argc,char*argv[]) linux獲得的,而標準輸入則是通過標準輸入函數例如linux中的scanf讀取到的。他們獲取的地方是不一樣的。例如:

echo?'main'?|?cat

這條命令會中cat會從其標準輸入中讀取內容并處理,也就是會輸出 ‘main’ 字符串。echo命令將其標準輸出的內容 ‘main’ 通過管道定向到 cat 的標準輸出中。

cat

如果僅僅輸入cat并回車,則該程序會等待輸入,我們需要從鍵盤輸入要處理的內容給cat,此時cat也是從標準輸入中得到要處理的內容的,因為我們的cat命令行中也沒有指定要處理的文件名。大多數命令有一個參數 ?– ?如果直接在命令的最后指定 – ?則表示從標準輸入中讀取,

例如:

echo?'main'?|?cat?-

這樣也是可行的,會顯示 ‘main’ 字符串,同樣輸入 cat – 直接回車與輸入 cat 直接回車的效果也一樣,但是如果這樣呢:

echo?'main'?|?cat?test.cpp?-

同時指定test.cpp 和 – 參數,此時cat程序還是會顯示test.cpp的內容。但是有一個程序的策略則不同,它是grep,例如:

echo?'main'?|?grep?'main'?test.cpp?-

該命令的輸出結果是:

test.cpp:int?main()  (standard?input):main

此時grep會同時處理標準輸入和文件test.cpp中的內容,也就是說會在標準輸入中linux ‘main’ 也會在文件 test.cpp (該文件名從grep命令行參數中獲得)中搜索 ‘main’。也就是說當命令行中 test.cpp 和 – 兩個參數同時存在的時候,不同的程序處理不同。我們看到了cat與grep處理就不同。但是有一點是一樣的 ?首先在命令行中查找要處理的內容的來源(是從文件還是從標準輸入,還是都有),如果在命令行中找不到與要處理的內容的來源相關的參數則默認從標準

輸入中讀取要處理的內容了。

另外很多程序是不處理標準輸入的,例如 kill , rm 這些程序如果命令行參數中沒有指定要處理的內容則不會默認從標準輸入中讀取。所以:

echo?'516'?|?kill

這種命里是不能執行的。

echo?'test'?|?rm?-f

這種也是沒有效果的。

這兩個命令只接受命令行參數中指定的處理內容,不從標準輸入中獲取處理內容。想想也很正常,kill 是結束進程,rm是linux文件,如果要結束的進程pid和要刪除的文件名需要

從標準輸入中讀取,這個也很怪異吧。 但是像 cat與grep這些文字處理工具從標準輸入中讀取待處理的內容則很自然。

但是有時候我們的腳本卻需要 echo ‘516’ | kill 這樣的效果,例如 ps -ef | grep ‘ddd’ | kill 這樣的效果,篩選出符合某條件的進程pid然后結束。這種需求對于我們來說是理所當然而且是很常見的,那么應該怎樣達到這樣的效果呢。有幾個解決辦法:

1. 通過

kill?`ps?-ef?|?grep?'ddd'`

這種形式,這個時候實際上等同于拼接字符串得到的命令,其效果類似于 ?kill $pid

2.

for?procid?in?$(ps?-aux?|?grep?"some?search"?|?awk?'{print?$2}');?do?kill?-9?$procid;?done

其實與第一種原理一樣,只不過需要多次kill的時候是linux處理的,每次處理一個

3.

?ps?-ef?|?grep?'ddd'?|?xargs?kill

OK,使用了xargs命令,鋪墊了這么久終于鋪到了主題上。xargs命令可以通過管道接受字符串,并將接收到的字符串通過空格分割成許多參數(默認情況下是通過空格分割) 然后將參數傳遞給其后面的命令,作為后面命令的命令行參數

xargs是什么,與管道有什么不同

xargs與管道有什么不同呢,這是兩個很容易混淆的東西,看了上面的xargs的例子還是有點云里霧里的話,我們來看下面的例子弄清楚為什么需要xargs:

echo?'--help'?|?cat

輸出:

--help  echo?'--help'?|?xargs?cat

輸出:

Usage:?cat?[OPTION]...?[FILE]...  Concatenate?FILE(s),?or?standard?input,?to?standard?output.  ?-A,?--show-all???equivalent?to?-vET  ?-b,?--number-nonblank?number?nonempty?output?lines  ?-e??????equivalent?to?-vE  ?-E,?--show-ends???display?$?at?end?of?each?line  ?-n,?--number????number?all?output?lines  ?-s,?--squeeze-blank??suppress?repeated?empty?output?lines  ?-t??????equivalent?to?-vT  ?-T,?--show-tabs???display?TAB?characters?as?^I  ?-u??????(ignored)  ?-v,?--show-nonprinting?use?^?and?M-?notation,?except?for?LFD?and?TAB  ??--help??display?this?help?and?exit  ??--version?output?version?information?and?exit

可以看到 echo ‘–help’ | cat ? 該命令輸出的是echo的內容,也就是說將echo的內容當作cat處理的文件內容了,實際上就是echo命令的輸出通過管道定向到cat的輸入了。然后cat從其標準輸入中讀取待處理的文本內容。這等價于在test.txt文件中有一行字符 ‘–help’ 然后運行 ?cat test.txt 的效果。

而 echo ‘–help’ | xargs cat 等價于 cat –help 什么意思呢,就是xargs將其接受的字符串 –help 做成cat的一個命令參數來運行cat命令,同樣 ?echo ‘test.c test.cpp’ | xargs cat 等價于 cat test.c test.cpp 此時會將test.c和test.cpp的內容都顯示出來。

xargs的一些有用的選項

相信到這里應該都知道xargs的作用了,那么我們看看xargs還有一些有用的選項:

1. -d 選項

默認情況下xargs將其標準輸入中的內容以空白(包括空格、Tab、回車換行等)分割成多個之后當作命令行參數傳遞給其后面的命令,并運行之,我們可以使用 -d 命令指定分隔符,例如:

echo?'11@22@33'?|?xargs?echo

輸出:

11@22@33

默認情況下以空白分割,那么11@22@33這個字符串中沒有空白,所以實際上等價于 echo 11@22@33 其中字符串 ’11@22@33′ 被當作echo命令的一個命令行參數

echo?'11@22@33'?|?xargs?-d?'@'?echo

輸出:

11?22?33

指定以@符號分割參數,所以等價于 echo 11 22 33 相當于給echo傳遞了3個參數,分別是11、22、33

2. -p 選項

使用該選項之后xargs并不會馬上執行其后面的命令,而是輸出即將要執行的完整的命令(包括命令以及傳遞給命令的命令行參數),詢問是否執行,輸入 y 才繼續執行,否則不執行。這種方式可以清楚的看到執行的命令是什么樣子,也就是xargs傳遞給命令的參數是什么,例如:

echo?'11@22@33'?|?xargs?-p?-d?'@'?echo

輸出:

echo?11?22?33

??…y ? ? ?==>這里詢問是否執行命令 echo 11 22 33 輸入y并回車,則顯示執行結果,否則不執行

?11 22 33 ? ==>執行結果

3. -n 選項

該選項表示將xargs生成的命令行參數,每次傳遞幾個參數給其后面的命令執行,例如如果xargs從標準輸入中讀入內容,然后以分隔符分割之后生成的命令行參數有10個,使用 -n 3 之后表示一次傳遞給xargs后面的命令是3個參數,因為一共有10個參數,所以要執行4次,才能將參數用完。例如:

echo?'11@22@33@44@55@66@77@88@99@00'?|?xargs?-d?'@'?-n?3?echo

輸出結果:

11?22?33  44?55?66  77?88?99  00

等價于:

echo?11?22?33  echo?44?55?66  echo?77?88?99  echo?00

實際上運行了4次,每次傳遞3個參數,最后還剩一個,就直接傳遞一個參數。

4. -E 選項,有的系統的xargs版本可能是-e ?eof-str

該選項指定一個字符串,當xargs解析出多個命令行參數的時候,如果搜索到-e指定的命令行參數,則只會將-e指定的命令行參數之前的參數(不包括-e指定的這個參數)傳遞給xargs后面的命令

echo?'11?22?33'?|?xargs?-E?'33'?echo

輸出:

11?22

可以看到正常情況下有3個命令行參數 11、22、33 由于使用了-E ’33’ 表示在將命令行參數 33 之前的參數傳遞給執行的命令,33本身不傳遞。等價于 echo 11 22 這里-E實際上有搜索的作用,表示只取xargs讀到的命令行參數前面的某些部分給命令執行。

注意:-E只有在xargs不指定-d的時候有效,如果指定了-d則不起作用,而不管-d指定的是什么字符,空格也不行。

echo?'11?22?33'?|?xargs?-d?'?'?-E?'33'?echo?=>?輸出?11?22?33  echo?'11@22@33@44@55@66@77@88@99@00?aa?33?bb'?|?xargs?-E?'33'?-d?'@'?-p?echo?=>?輸出?11?22?33?44?55?66?77?88?99?00?aa?33?bb  ##?-0?選項表示以?'

国产亚洲色婷婷久久99精品|
香蕉久久夜色精品国产2020|
国产精品乱码久久久久久软件
|
久久精品aⅴ无码中文字字幕不卡|
久久久久一本毛久久久|
国产三级观看久久|
欧洲国产伦久久久久久久|
亚洲乱码中文字幕久久孕妇黑人
|
久久亚洲精品成人av无码网站|
久久91精品久久91综合|
久久九九有精品国产23百花影院|
久久精品国产72国产精福利|
色偷偷88888欧美精品久久久|
思思久久精品在热线热|
国产免费久久精品99re丫y|
狠狠色丁香久久婷婷综合|
狠狠色丁香婷婷久久综合|
亚洲欧洲中文日韩久久AV乱码|
亚洲精品蜜桃久久久久久|
亚洲国产一成人久久精品|
丰满少妇高潮惨叫久久久|
99久久国产综合精品五月天喷水|
免费观看成人久久网免费观看|
91久久精品电影|
一本色道久久HEZYO无码|
99久久国产热无码精品免费|
嫩草影院久久国产精品|
久久综合九色综合网站|
亚洲伊人久久大香线蕉苏妲己|
久久av免费天堂小草播放|
久久国产精品一国产精品金尊|
国内精品久久久久久久久|
日韩精品无码久久一区二区三|
久久婷婷五月综合97色直播|
精品国产乱码久久久久久浪潮|
久久精品无码专区免费东京热|
久久影院午夜理论片无码|
狠狠色丁香婷婷综合久久来来去
|
久久国产精品成人免费|
亚洲中文字幕无码久久综合网
|
久久www免费人成看片|