Linux의 xargs 명령에 대한 자세한 설명과 xargs와 파이프의 차이점

黄舟
풀어 주다: 2017-06-07 10:04:55
원래의
1670명이 탐색했습니다.

문제의 원인인 xargs를 사용하는 이유

직장에서 특히 다른 사람이 작성한 스크립트에서 xargs 명령을 자주 접하게 되는데, 파이프라인과 혼동하기 쉽습니다. 이 기사에서는 이에 대해 자세히 설명합니다. xargs 명령, xargs 명령을 사용해야 하는 이유와 파이프와의 차이점. xargs를 사용하는 이유는 무엇입니까? linux 명령은 명령줄 매개변수와 표준 입력을 통해 두 곳에서 처리할 콘텐츠를 읽을 수 있다는 것을 알고 있습니다. 예를 들어 cat 및 grep은 다음과 같습니다.

echo 'main' | cat test.cpp
로그인 후 복사

이 경우 cat은 'main'string 대신 test.cpp의 내용을 출력합니다. 파일이 존재하지 않으며 표준 입력에서 읽으려는 시도가 없습니다. echo 'main' | 파이프라인을 통해 echo의 표준 출력(즉, 문자열 'main')을 cat의 표준 입력으로 가져옵니다. 즉, 이때 cat의 표준 입력에 내용이 있습니다. 그 내용은 'main' 문자열이지만 위 내용에서 cat은 표준 입력에서 처리할 내용을 읽지 않습니다. (참고: 표준 입력에는 버퍼가 있습니다. 프로그램에서 표준 입력을 읽기 위해 scanf 함수를 사용하는 것처럼 실제로는 표준 입력 버퍼에서 읽습니다.) 실제로, 기본적으로 많은 Linux 명령은 먼저 명령줄 매개변수에서 매개변수를 얻은 다음 프로그램에 반영되는 표준 입력에서 해당 매개변수를 읽도록 설계되었습니다. int main(int argc, char) *argv[]) 함수 매개변수를 얻고 C 언어에서 scanf와 같은 표준 입력 함수를 통해 표준 입력을 읽습니다. 얻는 곳이 다릅니다. 예:

echo 'main' | cat
로그인 후 복사

이 명령은 cat이 표준 입력에서 내용을 읽고 처리하도록 합니다. 즉, 'main' 문자열을 출력합니다. echo 명령은 표준 출력 'main'의 내용을 파이프를 통해 cat의 표준 출력으로 보냅니다.

cat
로그인 후 복사

그냥 cat을 입력하고 Enter를 누르면 프로그램은 입력을 기다리게 됩니다. 이때 cat은 처리할 내용을 키보드에서 입력받아야 합니다. , 왜냐하면 우리의 cat 명령에는 해당 줄에 지정된 처리할 파일 이름도 없기 때문입니다. 대부분의 명령에는 매개변수가 있습니다. 명령 끝에 직접 지정하는 경우 이는 표준 입력에서 읽는 것을 의미합니다.

예:

echo 'main' | cat -
로그인 후 복사

이것도 가능합니다. 'main' 문자열이 표시되며 cat을 입력해도 됩니다. 직접 return Enter를 누르는 효과는 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 파일의 내용을 다음 위치에서 처리합니다. 동시에 표준 입력에서 'main'을 검색하면 test.cpp 파일에서도 'main'을 검색합니다(파일 이름은 grep 명령줄 인수에서 가져옵니다). 즉, test.cpp와 -라는 두 매개변수가 명령줄에 동시에 존재할 경우 서로 다른 프로그램에서 이를 다르게 처리합니다. 우리는 cat과 grep이 다르게 처리되는 것을 보았습니다. 그러나 한 가지는 동일합니다. 처리할 콘텐츠의 소스와 관련된 매개변수를 찾을 수 없는 경우 먼저 명령줄(파일, 표준 입력 또는 둘 다에서)에서 처리할 콘텐츠의 소스를 찾습니다. 명령줄에서 기본적으로 처리할 콘텐츠는 표준 입력에서 읽혀집니다.

또한 많은 프로그램은 kill 및 rm과 같은 표준 입력을 처리하지 않습니다. 명령줄 매개변수가 처리할 내용을 지정하지 않으면 이러한 프로그램은 기본적으로 표준 입력에서 읽지 않습니다. 그래서:

echo '516' | kill
로그인 후 복사

이런 운명은 이루어질 수 없습니다.

echo 'test' | rm -f
로그인 후 복사

이것도 효과가 없습니다.

이 두 명령은 명령줄 매개변수에 지정된 처리 내용만 허용하고 표준 입력에서 처리 내용을 가져오지 않습니다. 생각해보면 당연한 일인데 Kill은 프로세스를 종료한다는 뜻이고 rm은 파일을 삭제한다는 뜻이다. 이것도 이상해요. 그러나 cat 및 grep과 같은 워드 프로세싱 도구가 표준 입력에서 처리할 콘텐츠를 읽는 것은 자연스러운 일입니다.

그러나 때로는 특정 조건을 충족하는 프로세스 pid를 필터링하고 종료하기 위해 스크립트에 ps -ef | grep 'ddd' | kill과 같은 효과가 필요합니다. 이러한 요구는 우리에게 자연스럽고 매우 흔한 일입니다. 그렇다면 이 효과를 어떻게 달성해야 할까요? 여러 가지 해결책이 있습니다: 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的时候是循环处理的,每次处理一个

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 选项表示以 '\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

실제로 개행 문자도 xargs의 기본 공백 문자 중 하나이기 때문에 xargs find .-name "*.txt" | xargs echo의 기본 공백 구분 기호를 사용할 수도 있습니다. find 명령이 -print0을 추가하지 않으면 실제로 검색 결과의 각 문자열 뒤에 줄바꿈이 추가됩니다.

위 내용은 Linux의 xargs 명령에 대한 자세한 설명과 xargs와 파이프의 차이점의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿