텍스트 파일의 각 줄을 명령의 인수로 전달하는 방법은 무엇입니까?


42

.txt파일 이름을 인수로 사용하여 파일을 한 줄씩 읽고 각 줄을 명령에 전달 하는 스크립트를 작성 하려고합니다. 예를 들어,, command --option "LINE 1"then command --option "LINE 2"등을 실행 합니다. 명령 출력이 다른 파일에 기록됩니다. 어떻게하면 되나요? 어디서부터 시작해야할지 모르겠습니다.

답변:


26

while read루프 사용 :

: > another_file  ## Truncate file.

while IFS= read -r LINE; do
    command --option "$LINE" >> another_file
done < file

또 다른 방법은 출력을 블록별로 리디렉션하는 것입니다.

while IFS= read -r LINE; do
    command --option "$LINE"
done < file > another_file

마지막으로 파일을 여는 것입니다.

exec 4> another_file

while IFS= read -r LINE; do
    command --option "$LINE" >&4
    echo xyz  ## Another optional command that sends output to stdout.
done < file

명령 중 하나를 입력을 읽어 경우, 명령을 먹지 않도록 입력을 다른 FD를 사용하는 것이 좋습니다 것 (가정 여기 ksh, zshbash에 대한 -u 3사용, <&3대신 이식) :

while IFS= read -ru 3 LINE; do
    ...
done 3< file

마지막으로 인수를 수락하려면 다음을 수행하십시오.

#!/bin/bash

FILE=$1
ANOTHER_FILE=$2

exec 4> "$ANOTHER_FILE"

while IFS= read -ru 3 LINE; do
    command --option "$LINE" >&4
done 3< "$FILE"

어느 것을 실행할 수 있습니까?

bash script.sh file another_file

추가 아이디어. 로 다음 bash을 사용하십시오 readarray.

readarray -t LINES < "$FILE"

for LINE in "${LINES[@]}"; do
    ...
done

참고 : IFS=행 값이 선행 및 후행 공백으로 잘리지 않는 경우 생략 할 수 있습니다.


28

다른 옵션은 xargs입니다.

GNU로 xargs:

< file xargs -I{} -d'\n' command --option {} other args

{} 텍스트 줄의 자리 표시 자입니다.

다른 xargs것들은 -d없지만, 일부는 -0NUL로 구분 된 입력을 가지고 있습니다. 이를 통해 다음을 수행 할 수 있습니다.

< file tr '\n' '\0' | xargs -0 -I{} command --option {} other args

Unix 호환 시스템 ( -IPOSIX에서는 선택 사항이며 Unix 호환 시스템에만 필요)에서 입력을 사전 처리하여 다음 과 같이 예상되는 형식으로 라인 을 인용 해야합니다 xargs.

< file sed 's/"/"\\""/g;s/.*/"&"/' |
  xargs -E '' -I{} command --option {} other args

그러나 일부 xargs구현의 경우 인수의 최대 크기 (예 : Solaris의 경우 255, Unix 사양에서 허용되는 최소값)에 대한 제한이 매우 낮습니다.


에 환원<file xargs -L 1 -I{} command --option {} other args
iruvar

@iruvar, 아니오, 따옴표를 처리하고 공백을 제거합니다.
Stéphane Chazelas

7

질문을 정확하게 유지 :

#!/bin/bash

# xargs -n param sets how many lines from the input to send to the command

# Call command once per line
[[ -f $1 ]] && cat $1 | xargs -n1 command --option

# Call command with 2 lines as args, such as an openvpn password file
# [[ -f $1 ]] && cat $1 | xargs -n2 command --option

# Call command with all lines as args
# [[ -f $1 ]] && cat $1 | xargs command --option

1
매력처럼 작동했습니다 :-)
BugHunter

3

내가 찾은 가장 좋은 대답은 다음과 같습니다.

for i in `cat`; do "$cmd" "$i"; done < $file

편집하다:

... 4 년 후 ...

몇 차례의 다운 투표와 더 많은 경험을 쌓은 후 다음을 추천합니다.

xargs -l COMMAND < file

3
파일의 각 단어 마다 한 번씩 명령을 호출 합니다. 또한 do "$cmd" "$i";이유가없는 한 쉘 변수에 대한 참조를 항상 인용해야 합니다. 파일 *자체에 단어가 포함되어 있으면 코드가 실행 $cmd *되며 물론 현재 디렉토리의 파일 목록과 함께 명령이 실행됩니다.
G-Man, 'Reinstate

1
@ G-남자는,를 제외하고 zsh는이 `cat`이미 확장 것 *(인용 부호로 둘러싸이지 않은가 $i여전히 와일드 카드 (두 번째 라운드)를 확장 할 수있는 경우의 확장을 `cat`소개하고 일부). 어쨌든 그 접근법은 실제로 잘못되었습니다.
Stéphane Chazelas

1
+1. 각 줄에 공백없이 사용되는 명령에 필요한 입력 만 포함되어 있으면 제대로 작동합니다.
Subin Sebastian

이것은 각 단어마다 작용합니다. 각 줄마다 작용하는 변형이 있습니까?
thebunnyrules

문제는 파일 이름 목록을 한 줄씩 처리하는 것이 었습니다.
Steffen Roller

2
    sed "s/'/'\\\\''/g;s/.*/\$* '&'/" <<\FILE |\
    sh -s -- command echo --option
all of the{&}se li$n\es 'are safely shell
quoted and handed to command as its last argument
following --option, and, here, before that echo
FILE

산출

--option all of the{&}se li$n\es 'are safely shell
--option quoted and handed to command as its last argument
--option following --option, and, here, before that echo

-2
ed file.txt
%g/^/s// /
2,$g/^/-,.j
1s/^/command/
wq
chmod 755 file.txt
./file.txt

파일의 모든 줄을 하나의 명령에 대한 인수로 전달하십시오.

command line1 line2 line3 ....

--option각 행 앞에 플래그가 필요하면 두 번째 명령을 다음과 같이 변경하십시오.

%g/^/s// --option /

1
ed ... 실제로 사용하는 -1은 무엇입니까?
user2217522

3
나는 당신을 공감하지 않았지만 아마도 다음과 같은 이유를 가진 사람은 : (1) 이것은 질문이 요구하는 것을하지 않습니다. 명령 행에서 파일의 모든 내용으로 명령을 한 번 호출합니다. 한 줄에 한 번 이 아닙니다 . (2) 이것은 쉘에 특별한 문자 (파일에있을 수 있음)를 처리하지 않습니다. 예를 들면, ', ", <, >, ;, 등 (3)이 불필요한 임시 파일을 생성한다. (4) 이와 같은 것은 일반적으로 "여기 문서"를 사용하여 수행됩니다. (5) 당신의 ed명령이 서투르다. 처음 두 명령은 %s/^/ /및 로 줄일 수 있습니다 %j.
G-Man, 'Reinstate
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.