wake-up-neo.com

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

ls | grep pattern -와 일치 할 때마다 Java 명령을 한 번 실행하고 싶습니다.이 경우 find pattern -exec Java MyProg '{}' \;를 수행 할 수 있다고 생각하지만 일반적인 경우- "모든 표준 입력 라인에 대해 명령을 한 번 실행"하는 쉬운 방법이 있습니까? (물고기 또는 배쉬)

176
Xodarap

그것이 xargs의 역할입니다.

... | xargs command
98
Keith

허용 된 답변 옳은 생각이 있지만, 열쇠는 xargs the -n1 스위치 : "출력 라인 당 한 번 명령 실행 :"

cat file... | xargs -n1 command

또는 단일 입력 파일의 경우 cat에서 파이프를 완전히 피하고 다음을 수행 할 수 있습니다.

<file xargs -n1 command
193
Michael Goldshteyn

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
117
Steven D

Keith에게 동의합니다. xargs는 작업을위한 가장 일반적인 도구입니다.

나는 보통 3 단계 접근법을 사용합니다.

  • 작업하고 싶은 것이 생길 때까지 기본 작업을 수행하십시오.
  • 올바른 구문을 얻도록 awk로 줄을 준비하십시오.
  • 그런 다음 xargs가 bash의 도움을 받아 실행하도록하십시오.

더 작고 빠른 방법이 있지만이 방법은 거의 항상 작동합니다.

간단한 예 :

ls | 
grep xls | 
awk '{print "MyJavaProg --arg1 42 --arg2 "$1"\0"}' | 
xargs -0 bash -c

첫 번째 두 줄은 작업 할 파일을 선택한 다음 awk는 실행할 명령과 일부 인수를 사용하여 Nice 문자열을 준비하고 $ 1은 파이프의 첫 번째 열 입력입니다. 마지막으로 xargs 가이 문자열을 bash로 보내어 실행시킵니다.

약간 과잉이지만이 레시피는 매우 유연하기 때문에 많은 곳에서 도움이되었습니다.

22
Johan

이런 종류의 작업을 위해 GNU Parallel이 만들어졌습니다. 가장 간단한 사용법은 다음과 같습니다.

cat stuff | grep pattern | parallel Java MyProg

자세한 내용은 소개 동영상을 참조하십시오. http://www.youtube.com/watch?v=OpaiGYxkSuQ

15
Ole Tange

또한 생선 껍질의 while read 루프 ( fish 태그를 사용한 것을 고려하면 생선 껍질을 원한다고 가정합니다).

command | while read line
    command $line
end

몇 가지 유의할 사항.

  • read-r 인수를 사용하지 않으며 가장 일반적인 사용 사례를 쉽게 만들기 위해 백 슬래시를 해석하지 않습니다.
  • Bash와 달리 물고기는 변수를 공백으로 구분하지 않으므로 $line를 인용 할 필요는 없습니다.
  • command 자체는 구문 오류 (자리 표시 자 인수의 이러한 사용을 잡기 위해)입니다. 실제 명령으로 바꾸십시오.
10
Konrad Borowski

잠재적으로 위생 처리되지 않은 입력을 처리 할 때, 전체 작업을 실행하기 전에 (특히 사람들의 우편함 청소와 같은 파괴적인 경우) 육안 검사를 위해 한 줄씩 '맞춤법'을보고 싶습니다.

그래서 내가하는 일은 매개 변수 목록 (예 : 사용자 이름)을 생성하고 다음과 같이 한 줄에 하나씩 레코드로 파일에 공급하는 것입니다.

johndoe  
jamessmith  
janebrown  

그런 다음 vim에서 목록을 열고 다음과 같이 실행해야하는 전체 명령 목록을 얻을 때까지 검색 및 바꾸기 식으로 맹 글링합니다.

/bin/rm -fr /home/johndoe  
/bin/rm -fr /home/jamessmith 

이런 식으로 정규 표현식이 불완전한 경우 어떤 명령에서 잠재적 인 문제가 발생하는지 확인할 수 있습니다 (예 : /bin/rm -fr johnnyo connor). 이렇게하면 정규식을 취소하고보다 안정적인 버전으로 다시 시도 할 수 있습니다. 이름 맹 글링은 Van Gogh, O'Connors, St. Clair, Smith-Wesson과 같은 모든 Edge 사례를 처리하기가 어렵 기 때문에 악명 높은 것으로 유명합니다.

set hlsearch은 (는) vim에서이 작업을 수행하는 데 유용합니다. 모든 일치 항목을 강조 표시하므로 일치하지 않는 경우 또는 의도하지 않은 방식으로 일치하는 항목을 쉽게 찾을 수 있습니다.

정규 표현식이 완벽하고 테스트/생각할 수있는 모든 사례를 포착하면 일반적으로 sed 표현식으로 변환하여 다른 실행을 위해 완전히 자동화 할 수 있습니다.

입력 행 수로 인해 육안 검사를 수행 할 수없는 경우에는 명령을 실행하기 전에 화면 (또는 더 나은 로그)에 명령을 에코하는 것이 좋습니다. 따라서 오류가 발생하면 어떤 명령이 발생했는지 정확하게 알고 있습니다 실패합니다. 그런 다음 원래 정규식으로 돌아가서 한 번 더 조정할 수 있습니다.

1
Marcin

여기에서 즉시 사용할 수있는 카피 페이스트 :

cat list.txt | xargs -I{} command parameter {} parameter

목록의 항목은 {} 위치에 배치되고 나머지 명령 및 매개 변수는 그대로 사용됩니다.

1
DustWolf

다른 답변과 같이 xargs로 가능합니다. 질문의 "한 줄에 한 번"부분에서 두 가지 특성을 구별해야합니다.

  1. 한 번 : -n 1를 사용하면 각 인수에 대해 명령이 정확히 한 번만 호출됩니다. 그러나 기본적으로 xargs는 인수가 공백으로 구분되어 있다고 가정합니다. 파일에 공백이 있으면 중단됩니다.
  2. 라인 당 : -d '\n'를 사용하거나 tr '\n' '\0'로 입력을 사전 처리하고 -0를 사용하십시오. 이것은 입력의 공백에 대해 명령을 강력하게 만듭니다.

최종 명령 행은 다음과 같습니다.

.... | xargs -n 1 -d '\n' <command>

또는 (tr 사용)

.... | tr '\n' '\0' | xargs -n 1 -0 <command>

명령이 여러 인수를 한 번에 처리 할 수있는 경우 (예 : grep 또는 sed) -n 1를 생략하여 작업 속도를 높일 수있는 경우가 많습니다.

0
krlmlr

프로그램이 파이프를 무시하지만 파일을 인수로 허용하는 경우 특수 파일 /dev/stdin를 가리킬 수 있습니다.

Java에 익숙하지 않지만 다음은 bash에서 어떻게 수행하는지에 대한 예입니다.

$ echo $'pwd \n cd / \n pwd' |bash /dev/stdin
/home/rolf
/

Bash가 \n를 개행으로 변환하려면 $가 필요합니다. 왜 그런지 잘 모르겠습니다.

0
Rolf

나는 이것을 선호한다-여러 줄 명령과 명확한 코드 허용

find -type f -name filenam-pattern* | while read -r F
do
  echo $F
  cat $F | grep 'some text'
done

심판 https://stackoverflow.com/a/3891678/248616

0
Nam G VU