-n이 1보다 큰 경우 -I{}를 -xargs'와 함께 사용하는 방법은 무엇입니까?

-n이 1보다 큰 경우 -I{}를 -xargs'와 함께 사용하는 방법은 무엇입니까?

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개의 매개변수가 전달됩니다 (모든 매개변수를 한 번에 전달 참조).shsh"$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>

관련 정보