파일 줄을 반복하는 방법?

이 파일이 있다고 말하세요 :

hello world hello world 

이 프로그램

#!/bin/bash for i in $(cat $1); do echo "tester: $i" done 

출력

tester: hello tester: world tester: hello tester: world 

for 공백을 무시하고 각 줄을 개별적으로 반복합니다. 즉, 마지막 두 줄은 다음으로 대체해야합니다.

tester: hello world 

따옴표 사용 for i in "$(cat $1)"; 결과 i에 전체 파일이 한 번에 할당됩니다. 무엇을 변경해야합니까?

답변

(9 년 후 🙂
제공된 두 답변 모두 마지막에 줄 바꿈없이 파일에서 실패합니다. 이렇게하면 마지막 줄을 효과적으로 건너 뛰고 오류가 발생하지 않으며 재난으로 이어질 것입니다. way :).

지금까지 찾은 가장 간결한 솔루션은 “Just Works”(bash 및 sh 모두) :

while IFS="" read -r LINE || [ -n "${LINE}" ]; do echo "processing line: ${LINE}" done < /path/to/input/file.txt 

더 자세한 내용은 StackOverflow 토론을 참조하세요. “while read “(Bash)는 파일 끝에 줄 바꿈이 없으면 파일의 마지막 줄을 읽습니까?

주의 :이 방법은 마지막 줄에 줄 바꿈을 추가합니다. 아직 없습니다.

댓글

  • 잘하셨습니다. 감사합니다! " 이미없는 경우 EOF에 추가 줄 바꿈이 추가됩니다. " 댓글
  • Tobias, 저는 ' 이것을 메모로 추가하겠습니다. 감사합니다.

답변

for IFS :

#!/bin/bash IFS=$"\n" # make newlines the only separator set -f # disable globbing for i in $(cat < "$1"); do echo "tester: $i" done 

그러나 개행 은 IFS 공백 문자, 시퀀스이므로 빈 줄을 건너 뜁니다. 그 중 1로 계산되고 선행 및 후행은 무시됩니다. zshksh93 (bash 아님)를 사용하여 IFS=$"\n\n"는 개행 문자가 특별히 처리되지 않도록합니다. 그러나 모든 뒤에있는 개행 문자 (후행 빈 행 포함)는 항상 명령 대체에 의해 제거됩니다.

또는 with read (더 이상 cat ) :

#!/bin/bash while IFS= read -r line; do echo "tester: $line" done < "$1" 

빈 줄이 유지되지만 줄 바꿈 문자로 올바르게 구분되지 않으면 마지막 줄을 건너 뜁니다.

p>

댓글

  • 감사합니다. ' < 전체 루프로. 지금은 완벽하게 말이되지만
  • IFS \ read -r line' in second example. Is really IFS =`가 필요합니까? IMHO는 충분히 말할 수 있습니다. while read -r line; do echo "tester: $line"; done < "$1"
  • @GrzegorzWierzowiecki IFS=는 선행 및 후행 공백 제거를 해제합니다. while IFS= read..에서 IFS가 효과가없는 이유는 무엇입니까?
  • @BenMares 글 로빙을 방지하려면 우리가 읽고있는 텍스트에 나타날 수있는 표현은 확장에서 일치하는 파일 이름으로 확장됩니다. 예를 들어 printf '%s\n' '*o' 'bar' >afile; touch foo; IFS=$'\n'; for i in $(cat afile); do echo "$i"; done를 시도해보세요.
  • while IFS= read -r line || [ "$line" ]; do는 줄 바꿈 문자로 제대로 구분되지 않은 후행 줄을 처리합니다. (하지만 다시 추가됩니다).

답변

가치가있는 일을 위해 자주 사용되며 while IFS= read...를 사용하는 정확한 방법을 기억할 수 없으므로 bash 프로필에서 다음 함수를 정의했습니다.

# iterate the line of a file and call input function iterlines() { (( $# < 2 )) && { echo "Usage: iterlines <File> <Callback>"; return; } local File=$1 local Func=$2 n=$(cat "$File" | wc -l) for (( i=1; i<=n; i++ )); do "$Func" "$(sed "${i}q;d" "$File")" done } 

이 함수는 먼저 파일의 줄 수를 결정한 다음 sed를 사용하여 한 줄씩 추출하고 각 줄을 단일 문자열 인수로 주어진 함수. 대용량 파일에서는 이것이 실제로 비효율적이라고 생각하지만 지금까지는 문제가되지 않았습니다 (물론이 환영을 개선하는 방법에 대한 제안).

사용법은 매우 달콤합니다 IMO :

>> cat example.txt # note the use of spaces, whitespace, etc. a/path This is a sentence. "wi\th quotes" $End >> iterlines example.txt echo # preserves quotes, $ and whitespace a/path This is a sentence. "wi\th quotes" $End >> x() { echo "$#"; }; iterlines example.txt x # line always passed as single input string 1 1 1 1 1 

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다