파이프된 입력 줄당 한 번씩 명령을 실행하시겠습니까?

파이프된 입력 줄당 한 번씩 명령을 실행하시겠습니까?

각 일치 항목에 대해 Java 명령을 한 번씩 실행하고 싶습니다 ls | grep pattern -. 이 경우에는 할 수 있을 것 같지만 find pattern -exec java MyProg '{}' \;일반적인 경우가 궁금합니다. "표준 입력의 각 줄에 대해 한 번씩 명령을 실행"이라고 말하는 쉬운 방법이 있습니까? (물고기나 배쉬에서.)

답변1

수락된 답변아이디어는 옳지만 핵심은 xargs스위치를 통과하는 -n1것입니다."명령줄당 최대 1개의 인수를 사용하세요.":

cat file... | xargs -n1 command

또는 단일 입력 파일의 경우 cat파이핑을 모두 피하고 다음을 사용할 수 있습니다.

<file xargs -n1 command

2020년 8월 5일에 업데이트됨:

나는 또한 사용자 Jander의 의견에 있는 제안에 응답하고 싶습니다. 이 제안은 일부 잘못된 정보가 포함되어 있음에도 불구하고 잘 지지되고 있습니다. 이에 대해서는 지금 설명하겠습니다.

(주장되는) 문제점을 언급하지 않고 -L옵션을 추천하기 위해 서두르지 마십시오.xargs후행 공백 함수일으킬 수 있습니다. 제 생각에는 이러한 변화는 득보다 실이 더 많을 것이며 확실히 다음과 같은 경우에 무리가 될 것입니다 -L 1.한 번에 하나의 비어 있지 않은 라인에서 작동. 공평하게 말하면 매뉴얼 페이지는 xargs명확 합니다.특징(즉, 문제)는 스위치와 함께 제공됩니다 -L.

Jander는 의견과 답변을 복음으로 받아들이는 대신 매뉴얼 페이지를 읽는 것처럼 지루한 작업을 수행할 시간이 없었던 서두르고 의심하지 않는 StackOverflow 청중에게 빠른 팁을 요청할 때 이러한 문제를 언급하지 않았으므로 해당 -L문제를 다루겠습니다. 이제 내 추론은 -L여행 중에 가져가는 모든 수하물을 자세히 살펴보지 않는 것이 매우 나쁜 조언이라는 것입니다.

에 대한 나의 경멸을 설명하기 위해 -L누군가(아마 훈련 중에 이 데이터 파일을 만든 고등학교 여름 인턴)가 실수로 입력한 다음 텍스트가 포함된 간단한 입력 파일을 생각해 보겠습니다. 증거는 다음과 같습니다.창 유형파일 이름. 다행히(카르마?) 경영진에 의해 귀하가 새로운 관리인으로 선정되었습니다.

testdata.txt

1
2␠
3

숫자가 포함된 줄에 공백 문자가 있으므로( 브라우저 글꼴에 해당 문자가 시각적으로 표시되지 않는 경우 2이전 코드에서 SYMBOL FOR SPACE숫자 뒤에 유니코드 문자 모양으로 표시됨 ) 명령은 다음과 같이 사용합니다.2xargs -L1

<testdata.txt xargs -L1 echo

..., 다음과 같은(아마도 놀라운) 출력이 생성됩니다.

1
2 3

-L이는 스위치 지시문 때문입니다.xargs공백으로 끝나는 줄에 다음 줄을 추가합니다., 이 동작은 후행 공백으로 인해 줄이 제대로 잘리지 않는 이상한 순간의 결과 출력에만 영향을 미칠 수 있습니다. 올바른 입력 파일이 나타날 때까지 기다리는 시한 폭탄 오류입니다.

반면에, 스위치를 사용하는 동일한 명령은 -n 1더 수용 가능한 출력을 생성합니다.xargs-L 1

1
2␠
3

그것은 최악이 아닙니다! "무서운" 옵션을 강제로 적용하는 대신 이 -L스위치를 사용하세요. 이로 인해 실행 중인 환경에 비해 너무 길다고 생각되는 명령줄이 발견되면 프로세스가 종료됩니다.-n-xxargsxargs

스위치의 지시에 따라 후행 공백이 있는 연속된 여러 줄로 구성된 입력 파일과 혼합물에서 "에이전트"라고 하는 화학 시약을 사용하는 -L경우 이들 모두가 하나로 연결되면 중간 스트림 종료가 발생할 수 있습니다.-xxargs슈퍼라인xargs'라는 정의를 넘어서줄이 너무 깁니다.명령줄의 경우. 상황이 흐려지기 시작하면 다음을 고려하십시오.줄이 너무 깁니다.xargs실행 중인 플랫폼에 대해 지정된 최대 길이를 기준으로 크기가 결정되며, 겉보기에 의한 추가 오프셋에 의해 결정됩니다.임의의 상수맨 페이지에 더 자세히 설명되어 있습니다. 귀찮은 부정 적분과 미적분학의 원리를 기억하시나요?임의의 상수+ C부정적분의 해를 적는 것을 잊었기 때문에 퀴즈나 시험에서 점수를 잃었습니까 ? 글쎄, 이것을 -L당신의 편리한 도구 상자에 추가하면 xargs, 그 말이 다시 당신의 등을 물게 될 것입니다.

반면에 Value -n는 이러한 긴 줄을 작은 한입 크기의 한 줄 덩어리로 자르고 공백으로 끝나는지 여부에 관계없이 각 덩어리에 제공된 명령을 한 번에 하나씩 실행합니다. 더 이상 긴 대기열이 없으며, 더 이상 갑자기 종료되어 뒤에서 찌르는 일이 없습니다. Et tu, Brute ?1xargsxargs -x

xargs 매뉴얼 페이지의 문구에 대한 선택적 Segue

왜 표현이 모호하고 불규칙한지 모르겠습니다.공백xargs다음과 같이 더 잘 정의되고 덜 모호한 옵션 대신 매뉴얼 페이지 전체에서 사용됩니다 .

  • 공간이 있는 경우공백하나 이상을 나타냅니다.ASCII 공간수치
  • 줄바꿈 이외의 공백(해당되는 경우)공백힌트)
  • 그룹에 인쇄할 수 없는 문자가 하나 이상 있습니다.{공백, 가로 탭}(만약에공백이 무서운 듀오의 동의어로 사용됨)

2021년 6월 15일에 업데이트됨:

@BjornW 사용자가 xargs명령당 한 번씩 명령을 실행하는 방법을 물었습니다.철사단지 입력된 단어가 아닌 입력된 내용입니다. (저는 댓글을 읽었으며 코로나19에 대응하는 데 7개월이 걸렸다는 점을 비난할 수밖에 없습니다:P).

원래 질문의 정신에 따라 내 답변을 더 많은 사용 사례에 적용할 수 있도록 이 특정 시나리오에 대해 자세히 논의하고 싶습니다.

다음 입력 파일을 고려하십시오. 실제 업무에서 접할 수 있는 다양한 Edge Case가 가득합니다.현실 세계™ (예: 선행/후행 공백, 공백만으로 구성된 줄, 빈 줄, 하이픈으로 시작하는 줄 [스위치를 도입하는 것으로 해석해서는 안 됨] 등):

lines.txt

a1 a22 a333 a4444
b4444 b333 b22 b1
␠␠c d e f g
hhh
ii jj kk␠
␠␠␠
-L and -x are the gruesome twosome

이전 입력 파일에서는 OPEN BOX빈 줄을 표시하기 위해 유니코드 문자 U+2423을 사용하고, SYMBOL FOR SPACE앞뒤 공백을 더 돋보이게 하기 위해 유니코드를 사용했습니다.

내용에 관계없이(내용 없음 포함) 전체적으로 취해 단일 인수로 명령에 전달되는 각 입력 줄에서 명령을 실행한다고 가정합니다. xargs아래 표시된 대로 이 작업을 수행합니다 (참고: printf예제 명령이 될 것이며 %q형식 지정자를 사용하여 제공된 인수가 공백이 있거나 인수가 빈 문자열인 경우 명확성을 위해 아포스트로피로 묶습니다. 모두 입력, 입력만 가능 hhh) "unscathed" 줄, %q출력에서 ​​볼 수 있듯이 인쇄할 수 없는 문자가 있는 경우 %qPOSIX $''인용 구문을 사용하여 이스케이프됩니다.]) :

<lines.txt xargs -n1 -d'\n' printf -- 'Input line: %q\n'

출력은 다음과 같습니다.

Input line: 'a1 a22 a333 a4444'
Input line: 'b4444 b333 b22 b1'
Input line: '   c d e f g'
Input line: ''
Input line: hhh
Input line: 'ii jj kk '
Input line: ''
Input line: '   '
Input line: '-L and -x are the gruesome twosome'
Input line: ''
Input line: ''
Input line: ''

그래서 거기에 있습니다. 이 스위치를 사용하면 인수가 끝나고 다음 인수가 시작되는 위치를 나타내기 위해 -d입력 파일에서 찾아야 하는 구분 기호를 지정할 수 있습니다 . 그 자체 로 충분히 똑똑하도록 xargs설정하면 다음과 같이 해석될 수 있습니다.'\n'xargsC 스타일 문자 이스케이프-d해당 페이지의 스위치 설명에 명시된 바와 같이 man이를 사용하여 xargs최소한의 노력으로 전체 입력 행을 선택한 명령에 대한 인수로 전달할 수 있습니다.

xargs또한 이 동작이 필요한 드문 경우에 대해 여러 입력 줄을 연결하고(이 단락 끝에서 자세히 설명할 주의사항과 함께) 다음과 같이 전달하는 데 사용할 수 있다는 점을 언급하고 싶습니다. 우리 명령에 대한 단일 인수입니다. 위의 호출 명령에서 -n스위치에 전달된 숫자를 프로세스에서 줄 끝이 제거된 xargs단일 인수로 병합되어야 하는 입력 줄 수를 나타내는 값으로 설정하면 됩니다. \n불행하게도 이러한 개행 제거 동작은 위의 xargs접근 방식을 많은 사용 사례에 적합하지 않게 만듭니다. 한 줄이 끝나고 다음 줄이 시작되는 위치를 나타내는 정보가 프로세스에서 손실되기 때문입니다.

답변2

Bash 또는 기타 Bourne 스타일 셸(ash, ksh, zsh 등)에서:

while read -r line; do command "$line"; done

read -r표준 입력에서 한 줄을 읽습니다( 백슬래시는 해석 read되지 않으므로 -r원하지 않습니다). 따라서 다음 중 하나를 수행할 수 있습니다.

$ command | while read -r line; do command "$line"; done  

$ while read -r line; do command "$line"; done <file

답변3

그게 다야 xargs.

... | xargs command

답변4

GNU Parallel은 이러한 작업을 위해 설계되었습니다. 가장 간단한 사용법은 다음과 같습니다.

cat stuff | grep pattern | parallel java MyProg

자세히 알아보려면 소개 비디오를 시청하세요.http://www.youtube.com/watch?v=OpaiGYxkSuQ

관련 정보