Heim > Artikel > Betrieb und Instandhaltung > Ausführliche Erklärung des Befehls xargs unter Linux und des Unterschieds zwischen xargs und Pipes
Ich komme bei der Arbeit oft mit dem Befehl xargs in Kontakt, insbesondere in Skripten, die von anderen geschrieben wurden, aber es ist leicht, mit Pipelines verwechselt zu werden Erklären Sie im Detail, was der Befehl xargs ist, warum Sie den Befehl xargs verwenden sollten und welchen Unterschied er zu Pipes macht. Warum xargs verwenden? Wir wissen, dass der Befehl linux den zu verarbeitenden Inhalt von zwei Stellen aus lesen kann, zum einen über die Befehlszeilenparameter und zum anderen über die Standardeingabe. Beispielsweise sind cat und grep solche Befehle:
echo 'main' | cat test.cpp
In diesem Fall gibt cat den Inhalt von test.cpp anstelle von „main“ aus.string Wenn test.cpp nicht vorhanden ist, meldet der Befehl cat, dass die Datei nicht vorhanden ist, und versucht nicht, von der Standardeingabe zu lesen. echo 'main' | importiert die Standardausgabe von echo (d. h. die Zeichenfolge 'main') über eine Pipeline in die Standardeingabe von cat. und sein Inhalt ist die Zeichenfolge „main“, aber im obigen Inhalt liest cat den zu verarbeitenden Inhalt nicht aus seiner Standardeingabe. (Hinweis: Die Standardeingabe verfügt über einen Puffer, genau wie wir die Funktion scanf zum Lesen aus der Standardeingabe im Programm verwenden, liest sie tatsächlich aus dem Standardeingabepuffer.) Tatsächlich sind viele Linux-Befehle grundsätzlich darauf ausgelegt, die Parameter zunächst aus den Befehlszeilenparametern abzurufen und sie dann aus der Standardeingabe zu lesen, die sich im Programm widerspiegelt. Die Befehlszeilenparameter werden über int main(int argc,) übergeben. char der Hauptfunktion). *argv[]) Funktionsparameter werden abgerufen und die Standardeingabe wird über die Standardeingabefunktion wie scanf in C-Sprache gelesen. Woher sie es bekommen, ist unterschiedlich. Zum Beispiel:
echo 'main' | cat
Dieser Befehl veranlasst cat, den Inhalt seiner Standardeingabe zu lesen und zu verarbeiten, d. h. es gibt die Zeichenfolge „main“ aus. Der echo-Befehl leitet den Inhalt seiner Standardausgabe „main“ über eine Pipe an die Standardausgabe von cat weiter.
cat
Wenn Sie einfach cat eingeben und die Eingabetaste drücken, wartet das Programm auf die Eingabe des zu verarbeitenden Inhalts über die Tastatur. Zu diesem Zeitpunkt erhält cat auch den Inhalt über die Standardeingabe verarbeitet werden, da der zu verarbeitende Dateiname nicht in unserer Cat-Befehlszeile angegeben ist. Die meisten Befehle haben einen Parameter – wenn dieser direkt am Ende des Befehls angegeben wird – bedeutet dies, dass aus der Standardeingabe gelesen wird,
Zum Beispiel:
echo 'main' | cat -
Dies ist auch machbar und zeigt „ main ' String, geben Sie auch cat ein – der Effekt des direkten Drückens der Eingabetaste ist der gleiche wie beim Eingeben von cat und dem direkten Drücken der Eingabetaste, aber was wäre, wenn:
echo 'main' | cat test.cpp -
Test.cpp und - Parameter gleichzeitig angeben, Zu diesem Zeitpunkt ist das Cat-Programm noch vorhanden. Der Inhalt von test.cpp wird angezeigt. Aber es gibt ein Programm mit einer anderen Strategie, es ist grep, zum Beispiel:
echo 'main' | grep 'main' test.cpp -
Die Ausgabe dieses Befehls ist:
test.cpp:int main() (standard input):main
Zu diesem Zeitpunkt verarbeitet grep die Standardeingabe und Dateien gleichzeitig Der Inhalt in test.cpp, das heißt, die Standardeingabe wird nach 'main' und der Datei test.cpp durchsucht (der Dateiname wird aus dem Befehlszeilenparameter grep ermittelt). wird nach „main“ gesucht. Das heißt, wenn die beiden Parameter test.cpp und - gleichzeitig in der Befehlszeile vorhanden sind, werden sie von verschiedenen Programmen unterschiedlich gehandhabt. Wir haben gesehen, dass cat und grep unterschiedlich verarbeitet werden. Aber eines ist immer dasselbe: Suchen Sie zuerst die Quelle des zu verarbeitenden Inhalts in der Befehlszeile (sei es aus einer Datei, einer Standardeingabe oder beidem), wenn die Parameter, die sich auf die Quelle des zu verarbeitenden Inhalts beziehen, nicht gefunden werden in der Kommandozeile Standardmäßig wird der zu verarbeitende Inhalt aus der Standardeingabe
gelesen. Außerdem verarbeiten viele Programme keine Standardeingaben, wie z. B. kill und rm. Diese Programme lesen standardmäßig nicht von der Standardeingabe, wenn die Befehlszeilenparameter nicht angeben, was verarbeitet werden soll. Deshalb:echo '516' | killDiese Art von Schicksal kann nicht ausgeführt werden.
echo 'test' | rm -fAuch das ist wirkungslos. Diese beiden Befehle akzeptieren nur den in den Befehlszeilenparametern angegebenen Verarbeitungsinhalt und beziehen den Verarbeitungsinhalt nicht aus der Standardeingabe. Wenn Sie darüber nachdenken, ist das normal. Kill bedeutet, den Prozess zu beenden, und rm bedeutet, die Datei
zu löschen. Wenn die PID des zu beendenden Prozesses und der Name der zu löschenden Datei ausgelesen werden müssen Standardeingabe, das ist auch der Fall. Es ist seltsam. Für Textverarbeitungstools wie cat und grep ist es jedoch selbstverständlich, zu verarbeitende Inhalte aus der Standardeingabe zu lesen. Aber manchmal benötigen unsere Skripte den Effekt von echo '516' |. Dieses Bedürfnis ist für uns natürlich und weit verbreitet. Wie können wir diesen Effekt erzielen? Es gibt mehrere Lösungen:
1. In der Form
entspricht dies tatsächlich dem Befehl, der durch das Zusammenfügen von Zeichenfolgen erhalten wird, und seine Wirkung ähnelt kill $pid2.kill `ps -ef | grep 'ddd'`
for procid in $(ps -aux | grep "some search" | awk '{print $2}'); do kill -9 $procid; done
其实与第一种原理一样,只不过需要多次kill的时候是循环处理的,每次处理一个
3.
ps -ef | grep 'ddd' | xargs kill
OK,使用了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还有一些有用的选项:
默认情况下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
使用该选项之后xargs并不会马上执行其后面的命令,而是输出即将要执行的完整的命令(包括命令以及传递给命令的命令行参数),询问是否执行,输入 y 才继续执行,否则不执行。这种方式可以清楚的看到执行的命令是什么样子,也就是xargs传递给命令的参数是什么,例如:
echo '11@22@33' | xargs -p -d '@' echo
输出:
echo 11 22 33
?...y ==>这里询问是否执行命令 echo 11 22 33 输入y并回车,则显示执行结果,否则不执行
11 22 33 ==>执行结果
该选项表示将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个参数,最后还剩一个,就直接传递一个参数。
该选项指定一个字符串,当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 选项表示以 '\0' 为分隔符,一般与find结合使用 find . -name "*.txt"
输出:
./2.txt ./3.txt ./1.txt => 默认情况下find的输出结果是每条记录后面加上换行,也就是每条记录是一个新行 find . -name "*.txt" -print0
输出:
./2.txt./3.txt./1.txt => 加上 -print0 参数表示find输出的每条结果后面加上 '\0' 而不是换行 find . -name "*.txt" -print0 | xargs -0 echo
输出:
./2.txt ./3.txt ./1.txt find . -name "*.txt" -print0 | xargs -d '\0' echo
输出:
./2.txt ./3.txt ./1.txt
xargs的 -0 和 -d '\0' 表示其从标准输入中读取的内容使用 '\0' 来分割,由于 find 的结果是使用 '\0' 分隔的,所以xargs使用 '\0' 将 find的结果分隔之后得到3个参数: ./2.txt ./3.txt ./1.txt 注意中间是有空格的。上面的结果就等价于 echo ./2.txt ./3.txt ./1.txt
Tatsächlich ist es auch möglich, das Standard-Leerzeichen-Trennzeichen von xargs find -name „*.txt“ | zu verwenden, da das Zeilenumbruchzeichen auch eines der Standard-Leerzeichen von xargs ist. Wenn der Befehl „find“ nicht „-print0“ hinzufügt, wird tatsächlich nach jeder Zeichenfolge in den Suchergebnissen eine neue Zeile eingefügt.
Das obige ist der detaillierte Inhalt vonAusführliche Erklärung des Befehls xargs unter Linux und des Unterschieds zwischen xargs und Pipes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!