파일의 줄을 반복하는 방법은 무엇입니까?

파일의 줄을 반복하는 방법은 무엇입니까?

다음 파일이 있다고 가정해 보겠습니다.

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무엇을 바꿔야 하나요?

답변1

그리고 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로 계산되며 선행 및 후행 시퀀스는 무시됩니다. zshand ksh93(아님 )을 사용하면 특별한 처리 없이 개행 문자로 bash변경할 수 있습니다 .IFS=$'\n\n'뒤따라개행 문자(후행 공백 행 포함)는 항상 명령 대체에 의해 제거됩니다.

또는그리고read(더이상 cat):

#!/bin/bash

while IFS= read -r line; do
  echo "tester: $line"
done < "$1"

여기에는 빈 줄이 유지되지만 개행 문자로 적절하게 구분되지 않으면 마지막 줄을 건너뜁니다.

답변2

(9년 후:)
제공된 두 답변 모두 끝에 개행 문자가 없는 파일에서는 실패합니다. 이는 마지막 줄을 효과적으로 건너뛰고 오류가 발생하지 않으며 재앙으로 이어질 것입니다(어려운 방법으로 배웠습니다 :).

지금까지 "Just Works"(bash 및 sh에서)로 찾은 가장 깨끗한 솔루션은 다음과 같습니다.

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

보다 심층적인 토론을 보려면 다음 StackOverflow 토론을 참조하세요.파일 끝에 개행 문자가 없는 경우 "읽을 때"(Bash)를 사용하여 파일의 마지막 줄을 어떻게 읽습니까?

참고: 개행 문자가 없는 경우 이 방법은 마지막 줄에 추가 개행 문자를 추가합니다.

답변3

피할 수 있다면 하지 마세요. 특히 텍스트 작업을 할 때는 더욱 그렇습니다.

대부분의 텍스트 유틸리티는 한 번에 한 줄씩 텍스트를 처리하도록 설계되었으며, 적어도 GNU 구현의 경우 효율적이고 정확하게 처리하며 오류 조건을 잘 처리합니다. 파이프라인을 통해 병렬로 실행한다는 것은 여러 프로세서를 활용하여 작업을 수행할 수 있음을 의미합니다.

여기:

<input.txt sed 's/^/tester /' > output.txt

또는:

<input.txt awk '{print "tester", $0}' > output.txt

자세한 내용은 다음을 방문하십시오.쉘 루프를 사용하여 텍스트를 처리하는 것이 왜 나쁜 습관으로 간주됩니까?

텍스트 처리와 관련이 없고 파일의 각 줄에서 몇 가지 명령을 실행해야 하는 경우 xargs다음을 수행할 수 있는 GNU에 유의하세요.

xargs -rd'\n' -I@ -a input.txt cp -- @ @.back

예를 들어.

Bash 쉘을 사용하면 내장 명령을 사용하여 파일의 각 줄을 배열에 넣을 수 있습니다 readarray.

readarray -t lines < input.txt &&
  for line in "${lines[@]}"; do
    do-some-non-text-processing-you-cannot-easily-do-with-xargs "$line" || break
  done

POSIXly에서는 루프 내에서 닫는 다른 fd를 IFS= read -r line사용하여 일부 입력에서 한 줄을 수 있습니다 .while read

while
  IFS= read -r line <&3 ||
    [ -n "$line" ] # to cover for an unterminated last line.
do
  {
    do-some-non-text-processing-you-cannot-easily-do-with-xargs "$line" ||
      break # abort upon failure if relevant
  } 3<&-
done 3< input.txt > output.txt

read -r line읽는 줄에서 선행 및 후행 공백 문자를 제거합니다(변수에 있는 경우) $IFS. 그러나 yash쉘만 POSIX 요구 사항을 따릅니다. 대부분의 쉘에서는 공백과 탭으로 제한됩니다. ksh93 및 최신 버전에서는 bash로케일에서 공백으로 처리되는 모든 단일 바이트 문자에 대해 이 작업을 수행합니다.

따라서 줄을 읽고 앞뒤 공백을 제거하려면 다음을 수행할 수 있습니다 IFS=$' \t' read -r line. ksh93, yash1 또는 최신 버전 의 bash.IFS=$' \t\r'


yash구문 $'...'은 아직 지원되지 않지만 해당 구문이 필요 합니다 IFS=$(printf ' \t\r').

답변4

새 줄로 끝나는지 여부에 관계없이 모든 줄을 읽으려면 다음을 수행하십시오.

cat "somefile" | { cat ; echo ; } | while read line; do echo $line; done

출처: 내 오픈 소스 프로젝트https://sourceforge.net/projects/command-output-to-html-table/

관련 정보