grep
특정 문자열을 처리 해야 하는 파일(수만 개)이 많습니다 . 파일의 작은 부분에 공백이 있습니다. 파일이 너무 많으면 프로세스 생성의 오버헤드가 -n1
실제로 파일 검색 자체보다 더 큽니다.
이것은 작동하지만 너무 느리기 때문에 유용하지 않습니다.
cat filelist | xargs -I{} grep mystring '{}'
grep
따라서 다음과 같이 각 인스턴스에 1000개의 매개변수를 전달 하고 싶습니다 .
cat filelist | xargs -n1000 -I{} grep mystring '{}'
하지만 이건 작동하지 않아. =1 일 때만 {}
작동하는 것 같나요? !-n
예:
프로세스가 너무 많습니다. 올바른 출력입니다. $ 시퀀스 1 10 | xargs -I{} -n1 에코 "<{}>" <1> <2> <3> <4> <5> <6> <7> <8> <9> <10>
많은 과정이 있는데...뭐죠? $ 시퀀스 1 10 | xargs -I{} -n2 에코 "<{}>" <{}> 1 2 <{}> 3 4 <{}> 5 6 <{}> 7 8 <{}> 9 10
어쩌면 내가 대신 사용할 수도 있을 것 같아요 find
.
답변1
예, -I
한 번에 하나의 매개변수에만 작동합니다. 사용 시 입력은 사용되지 않을 때(사용 여부에 관계없이) -I
와는 다르게 매개변수로 구문 분석됩니다 .-n
비어 있지 않은 각 줄에 대해 하나의 단어가 있으며 -I{}
(개행은 백슬래시로 인용하여 포함할 수 있다는 점 제외) 선행 공백 문자는 제거되지만 후행 공백 문자는 제거되지 않습니다(목록은 일부 구현 및 로케일에 따라 다름). . 따옴표( "
, 및 는 여전히 '
s 와 \
다르게 처리됩니다 .)sh
그렇지 않은 경우 -I{}
단어는 공백(적어도 SPC, TAB 및 NL)으로 구분되고 따옴표가 처리됩니다.
비교하다:
$ printf ' a "b c" \n' | xargs -n1 printf '<%s>\n'
<a>
<b c>
$ printf ' a "b c" \n' | xargs -I{} printf '<%s>\n' {}
<a b c >
IMO, xargs
약간 혼란스럽습니다. 이를 사용하는 신뢰할 수 있고 유용한 유일한 방법은 GNU 확장을 -0
사용하는 것입니다.-d
한 번에 여러 인수가 포함된 명령을 실행하고 각 인수에 대해 다른 자리 표시자를 사용하려면 다음을 사용하는 것이 좋습니다 sh
.
xargs < filelist -r -n2 sh -c 'printf "1: %s\n2: %s\n" "$1" "$2"' sh
여기서는 및 자리 표시자를 사용하여 xargs
한 번에 2개의 매개변수가 전달됩니다 (모든 매개변수를 한 번에 전달 참조).sh
sh
"$1"
"$2"
"$@"
이것이 기본 단어 토큰화입니다 xargs
. filelist
각 줄에 하나의 파일이 포함되어 있으면 GNU xargs
의 -d '\n'
.
귀하의 예에서는 다음과 같이 할 필요가 grep
없습니다 .-n
-I
xargs < filelist grep mystring
그런 다음 xargs
가능한 한 많은 매개변수가 전달됩니다 grep
(매개변수는 끝에 추가됩니다). -r
이 것(GNU 확장자) 없이 마치 filelist
모두 비어 있는 것처럼 할 수 있고 grep
파일 인수(차단할 -r
) 없이 계속 실행하는 것은 filelist
.
-H
그러나 GNU의 options 을 사용 grep
하거나 다음과 같이 실행할 수 있습니다.
xargs < filelist grep mystring /dev/null
grep
일치하는 항목이 발견되면 파일 이름에 filelist
단어가 하나만 포함되어 있어도 항상 파일 이름을 인쇄 해야 합니다 .
답변2
이것은 작동합니다:
xargs -I '{}' -n 1 -P 1000 grep mystring '{}' < file_list.txt
- -나교체-str
- -N최대 매개변수
- -피최대 프로세스 수
답변3
-I{}
논평할 수는 없지만 지정된 수의 args 를 가진 함수가 필요한 다른 사람들과 관련이 있을 수 있다고 생각합니다 -n
.
내 경우에는 한 번에 하나의 인수만 대상 명령에 전달하고 싶지만아니요위치 매개변수로. 입력 인수를 대상 명령으로 전달해야 합니다.옵션, 옵션 뒤에는 대상 명령에 대한 추가 상용구 구성 요소가 옵니다.
예:target-command -opt="input-arg-1" -x -y some/path
따라서 일반 xargs는 명령 끝에 입력 arg를 추가하기 때문에 작동하지 않습니다. xargs -I{}
입력 구분 기호를 깨고 한 번에 하나의 입력 매개변수에 대해서만 작동하기 때문에 작동하지 않습니다 . 저는 Darwin과 Linux용으로 개발 중이며 (제가 아는 한) 두 플랫폼 모두 Bash 설치에 사용할 수 있는 옵션 조합이 없습니다.
@Stéphane의 대답은 내 솔루션의 핵심입니다. 대상 명령을 서브셸로 래핑하고 위치 매개변수를 사용하여 입력 매개변수를 추출할 수 있습니다. 이것은 나를 위해 일한 실제 코드 줄입니다.
echo $MODULES | xargs -n1 sh -c 'terraform -chdir="$1" init' --
-I
입력을 올바르게 구문 분석할 수 있도록 xargs가 args를 사용하지 않고 작업을 수행하도록 합니다 . 그런 다음 인수를 대상 명령에 삽입할 수 있는 하위 쉘에 전달합니다.
명령 --
끝에 sh -c
. 이는 sh에게 후속 인수를 일반 위치 인수로 서브쉘에 전달하도록 지시합니다. 나는 이것을 Bash와 BusyBox(ash)로 테스트했고 둘 다 작동했습니다. 다른 쉘에도 비슷한 기능이 있지만 아직 살펴보진 않았습니다.
답변4
GNU Parallel은 이 문제를 해결했습니다. -X에는 다음 컨텍스트가 포함됩니다.
$ seq 1 10 | parallel -j1 -qX echo "<{}>"
<1> <2> <3> <4> <5> <6> <7> <8> <9> <10>
-m은 다음을 수행하지 않습니다.
$ seq 1 10 | parallel -j1 -qm echo "<{}>"
<1 2 3 4 5 6 7 8 9 10>