UTF-8(BOM 포함/제외)로 인코딩된 두 개의 파일이 있습니다.
/tmp/bom$ ls
list.bom.txt list.nobom.txt
/tmp/bom$ cat list.nobom.txt
apple
banana
avocado
寿司
melon
/tmp/bom$ diff list.nobom.txt list.bom.txt
1c1
< apple
---
> apple
/tmp/bom$ file list.nobom.txt list.bom.txt
list.nobom.txt: UTF-8 Unicode text
list.bom.txt: UTF-8 Unicode (with BOM) text
두 파일의 유일한 차이점은 헤더 BOM 입니다 EF BB BF
.
그런 다음 "a"로 시작하는 줄을 필터링하기 위해 캐럿을 사용하여 짧은 awk 스크립트를 작성했습니다.
/tmp/bom$ gawk '/^a.*/' list.nobom.txt
apple
avocado
/tmp/bom$ gawk '/^a.*/' list.bom.txt
avocado
불행하게도 헤더 BOM의 경우 apple
첫 번째 줄은 무시됩니다.
그래서 내 질문은 다음과 같습니다이 문제를 해결할 수 있는 방법이 있나요?
나는 세 가지 해결책을 고려합니다.
BOM 바이트를 직접 작성합니다. 예를 들어,
gawk 'BEGIN { pat = "^(\xef\xbb\xbf)?a.*" } $0 ~ pat { print }'
UTF-8에서 작동합니다. 그러나 다른 인코딩은 처리하지 않습니다. 또한 너비가 0인 잘림 방지 공백으로 사용되는 U+FEFF가 있는 경우 위 스크립트가 실패하는 경우도 있습니다(설명 참조).
recoding을 사용하여 BOM 바이트를 제거합니다
nkf
. 예를 들어,nkf --oc=UTF-8 list.bom.txt | gawk '/^a.*/'
일하다. 그래도 좀 더 정교한 방법이 있는지 알고 싶습니다.
[추가됨] 이는 bash 기능을 사용하여 첫 번째 개선 사항입니다.
gawk -v bom="$(echo -e '\uFEFF')" ' NR == 1 { pat = "^" bom; sub(pat, "") } /^a.*/ { print } '
이는 BOM 유무에 관계없이 UTF-8에서 작동합니다. 그러나 이것은 내 환경의 UTF-16에서는 작동하지 않습니다. 따라서 두 번째 옵션이 더 좋습니다.
grep
그리고 이는 정규식 매칭 sed
이나 다른 스크립트를 사용하는 경우에도 문제가 된다고 생각합니다. 따라서 일반적인 해결책이 있다면 더욱 감사하겠습니다.
답변1
UTF-8에서는 BOM이 의미가 없습니다. 이는 일반적으로 Microsoft 운영 체제의 가짜 소프트웨어 버그로 인해 추가됩니다.
dos2unix
이는 제거되고 Windows 텍스트 파일의 다른 특성이 처리됩니다.
dos2unix < file.win.txt | awk ...