텍스트 파일을 한 줄씩 읽는 코드 줄이 있습니다.
텍스트 파일은 Windows 사용자가 생성하는 경우도 있고 Unix 사용자가 생성하는 경우도 있습니다. 그래서 때로는 줄의 끝이 보이기도 \r\n
하고 때로는 그냥 보이기도 합니다 \n
.
내 스크립트가 두 경우를 모두 처리하고 개행 문자가 \r
, 또는 \n
, \r\n
또는 인지 여부에 관계없이 각 줄에 개별적으로 도달하기를 원합니다 \n\r
.
while read -r textFileLines; do ... something ...; done < text_file.txt
이 코드일하다\n\r
각 줄 끝에 (LF CR)이 있지만아니요내가 \r\n
줄 끝에 있을 때!
시험
다음을 사용하여 새 텍스트 파일을 만듭니다.
Notepad++ v7.5.4
while read -r LINE; do echo "$LINE"; done < /cygdrive/d/test_text.txt
터미널 출력:
first_line second_line third_string
fourth_output
이 행이 표시 되지 않는 이유는 무엇인가요 ?
답변1
일부 파일은 DOS 텍스트 파일이고 다른 파일은 Unix 텍스트 파일인 경우 스크립트는 다음과 같은 방법으로 모든 데이터를 전달할 수 있습니다 dos2unix
.
dos2unix <filename |
while IFS= read stuff; do
# do things with "$stuff"
done
결과적으로 Unix 텍스트 파일은 수정되지 않습니다.
Mac 줄 바꿈 문제를 추가로 처리하기 위해 저는믿다당신은 할 수 있어야합니다
dos2unix <filename | mac2unix |
while IFS= read stuff; do
# do things with "$stuff"
done
마지막 줄은 read
종료되지 않아 전혀 줄이 아니기 때문에 루프에 의해 출력되지 않습니다.
파일의 마지막 줄에 종료 개행 문자가 없는지 감지하고 그렇지 않은 경우 다음 위치에 추가하십시오 bash
.
if [ "$( tail -c 1 filename )" != $'\n' ]; then
printf '\n' >>filename
fi
관련된:
답변2
fourth_output
이 행이 표시 되지 않는 이유는 무엇인가요 ?
이미지에서 파일의 마지막 줄 끝에 개행 문자가 누락되었습니다. read
구분 기호(새 줄)를 읽는 경우에만 true를 반환하고, 마지막 줄의 끝에 해당 구분 기호가 존재하지 않기 때문에 read
false를 반환하고 마지막 불완전한 줄을 인쇄하지 않고 루프가 종료됩니다.
이는 캐리지 리턴과 관련이 없으며 마지막 줄에 NL이 없으면 NL만 있어도 동작은 동일합니다.
file1
CRLF 줄로 끝나는 두 줄은 다음과 같습니다 .
$ cat -A file1
foo^M$
bar^M$
$ while read x ; do echo "<$x>"; done < file1
>foo
>bar
file2
두 번째 줄 끝에 있는 줄이 누락되었습니다.
$ cat -A file2 ; echo
foo^M$
bar
$ while read x ; do echo "<$x>"; done < file2
>foo
루프가 마지막 줄 조각도 처리하도록 하려면 반환에 실패할 read
때 변수에 데이터가 포함되어 있는지 확인 해야 합니다.read
$ while read -r x || [ "$x" ] ; do echo "<$x>"; done < file2
>foo
<bar>
CR을 제거하려면 루프(예: Bash/ksh/zsh)에서 제거하거나 x=${x%$'\r'};
or와 같은 전처리기 파일을 사용할 수 있습니다.tr -d '\r'
dos2unix
답변3
구현하다:
$ [ -n "$(tail -c1 infile)" ] && echo >> infile
$ sed 's/\r$\|^\r//g;s/\r/\n/g' infile | while IFS= read -r line
> do echo "$line" ; done
DOS line
second DOS
old mac line
new mac line
end\n\rreverse
linux line
new linux line
모든 문제가 해결되었습니다.
설명하다:
누락된 마지막 개행 문자를 수정하려면 다음을 사용하십시오.
[ -n "$(tail -c1 infile)" ] && echo >> infile
후행 줄 바꿈은 필요한 경우에만 추가됩니다(올바른 파일은 변경되지 않음).
그러면 변환할 수 있습니다
\r\n
(DOS 스타일) ~\n
(줄 끝의 \r만 제거)\n\r
(잘못된 DOS 스타일?)을 1로\n
(줄 시작 부분에서 \r 제거)- 그런 다음 (수정된 MAC의 경우)
\r
(이전 MAC)을 다음으로 변환합니다.\n
(GNU) sed를 한 번만 호출하세요.
sed 's/\r$\|^\r//g;s/\r/\n/g' infile
텍스트 파일이 다음 테스트 파일과 같은 경우:
$ cat infile
DOS line
second DOS
new mac line
end\n\rreverse
linux line
new linux line
no end line
$ cat -A infile
DOS line^M$
second DOS^M$
old mac line^Mnew mac line$
end\n\rreverse$
^Mlinux line$
new linux line$
no end line
$ od -An -tc infile
D O S l i n e \r \n
s e c o n d D O S \r \n
o l d m a c l i n e \r
n e w m a c l i n e \n
e n d \ n \ r r e v e r s e \n \r
l i n u x l i n e \n
n e w l i n u x l i n e \n
n o e n d l i n e
답변4
이를 수행하기 위한 명확한 도구가 있습니다. 파일에서 제거 하는 데 사용할 수 있는 보다 일반적인 것은 \r\n
입니다 dos2unix
.
시스템에서 이 기능을 사용할 수 없는 경우 다음 명령 중 하나를 사용하여 textFileLines
변수에 대해 유사한 작업을 수행할 수 있습니다.
$ echo "$textFileLines" | awk 1 RS='\r\n' ORS=
sed 1
$ echo "$textFileLines" | sed -e 's/\r//g'
sed 2
$ echo $textFileLines | sed $'s/\r//'
티
$ echo "$textFileLines" | tr -d '\r'
물론 이를 수행하는 다른 방법도 많이 있습니다. 이는 가장 일반적인 방법 중 일부일 뿐입니다.