일부 파일을 정규화하려고 하는데 SED와 일치하는 패턴을 찾을 수 없어 성공하지 못했습니다. Notepad++에서는 줄 끝에 CRLF가 명확하게 표시됩니다.
인쇄할 수 없는 문자를 볼 때^M와 cat
하나^M 또는\r줄 끝.
메모장++에서 검색할 수 있습니다.\r\n\h+캐리지 리턴과 CC를 연결할 공백을 제거합니다. 모두 한 줄에 있습니다(때로는 여러 줄 바꿈이 있을 수 있음).
SED Whiteout으로 모든 조합을 성공적으로 시도한 것 같습니다. 저도 이 링크 확인했어요https://stackoverflow.com/questions/3569997/how-to-find-out-line-endings-in-a-text-file
내가 무엇을 놓치고 있나요?
실패한 시도의 예
sed -En 's/\r\s+//g' $NewFile
sed -En 's/\r +//g' $NewFile
sed -En 's/\r\n +//g' $NewFile
sed -En 's/\n +//g' $NewFile
답변1
쉬운 수정은 \r
줄 끝에서 검색하는 정규식을 사용하는 것입니다( sed
파일을 읽을 때 처리되지만 정규식 앵커를 사용하여 감지할 수 있음 $
).
sed 's/\r$//' file.dos >file.txt
sed
리터럴 지원이 없으면 스크립트 \r
에 리터럴 캐리지 리턴을 포함하는 Bash "C 스타일" 문자열을 사용해 보세요 sed
.
sed $'s/\r$//' file.dos >file.txt
...또는 기호 표현이 표준인 Awk를 사용하세요.
awk '{ sub(/\r$/, "") } 1' file.dos >file.txt
...또는 dos2unix
논리를 바이너리로 캡슐화하는 이 도구를 사용하세요.
dos2unix file.dos
당신은 또한 볼 수 있습니다https://stackoverflow.com/questions/39527571/are-shell-scripts-sensitive-to-encoding-and-line-endings
이 전처리 후에 표준 이메일 도구를 사용하여 헤더를 추출할 수 있습니다. Procmail은 모든 헤더 행의 접기를 제공 formail -c
하거나 추가할 수 있습니다 -z
. 또는 간단한 Awk 단일 행을 사용할 수도 있습니다.
awk '!body { if(NR > 1 && $0 ~ /^[^ \n]/) printf "\n"; printf "%s", $0 }
/^$/ { printf "\n"; body=1 }
body'
물론 원한다면 sub
이전 Awk 솔루션의 작업을 이 스크립트의 상단에 추가 할 수 있습니다.
답변2
sed는 기본적으로 한 번에 한 줄만 확인하고 버퍼에 개행 문자도 포함하지 않으므로 쉬운 방법은 s/\r\n/.../
말할 것도 없고 그런 일도 할 수 없습니다. s/\r\n +//
전체 파일을 한 번에 처리하도록 예약해야 합니다.
이것이 sed에서 쉽게 수행될 수 있는지는 확실하지 않지만 적어도 GNU sed에서는 -z
개행 문자 대신 NUL 바이트를 구분 기호로 사용하는 옵션을 사용할 수 있습니다. 텍스트 파일에는 NUL이 있어서는 안 됩니다. 따라서 실제로는 전체 파일을 읽는 효과가 있습니다.
예를 들어 다음 입력 파일을 사용합니다.
$ cat -A foo.txt
from: foo bar^M$
to: someone ^M$
someone else^M$
cc: something ^M$
something else^M$
^M$
다음과 같이 작동할 수 있습니다.
$ sed -z -Ee 's/\r\n +//g' foo.txt |cat -A
from: foo bar^M$
to: someone someone else^M$
cc: something something else^M$
^M$
또는 옵션을 통해 전체 파일을 읽을 수 있는 Perl을 사용할 수도 있습니다 -0777
.
$ perl -0777 -pe 's/\r\n +//g' foo.txt |cat -A
from: foo bar^M$
to: someone someone else^M$
cc: something something else^M$
^M$
하지만 이메일 헤더 처리에 대한 규칙이 무엇인지 잘 모르므로 이에 대해서는 언급하지 않겠습니다. 하지만 이메일 처리를 위한 도구/라이브러리/모듈이 이미 있다는 점에 유의하세요. 또한 동일한 파일에 메시지 데이터가 있는 경우 여기서 수행하는 작업도 메시지 데이터를 손상시킵니다.
답변3
우선, SED 사용 과정을 이해하는 것은 고사하고 이 작업을 완료할 수 없었더라도 저를 올바른 방향으로 안내하고 응답해 주신 모든 분들께 감사드립니다. @seshoumara가 제안한 대로 -z 옵션과 dos2unix 유틸리티를 사용해 보았지만 어떤 이유로 작동하지 않는 것 같습니다. @ilkkachu 님께서도 풍부한 정보를 제공해 주셨네요.
그래서 길고 철저한 조사 끝에 나는 다음과 같은 결론에 도달했습니다. 첫 번째 줄은 공백이 발견될 때까지 이메일 헤더를 추출하고, 두 번째 줄은 공백을 정규화합니다.
sed -n '0,/^\r/p' $f | tee bk/$NewFile
sed -Ei ':Loop ; $!N ; s/\n\s+/ / ; tLoop ; P ; D' bk/$NewFile
줄 끝은 \r, \n 또는 \r\n을 사용할 때 가장 큰 문제였으며 dos2unix를 사용하면 그 문제가 해결되었습니다. 첫 번째 명령에서는 \r을 사용할 수 있었지만 두 번째 명령에서는 사용할 수 없었던 이유를 잘 모르겠습니다(나중에 저장하겠습니다).