BOM이 포함된 AWK: 정규식을 사용하여 유니코드 BOM을 처리할 수 있는 멋진 방법이 있습니까?

BOM이 포함된 AWK: 정규식을 사용하여 유니코드 BOM을 처리할 수 있는 멋진 방법이 있습니까?

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첫 번째 줄은 무시됩니다.

그래서 내 질문은 다음과 같습니다이 문제를 해결할 수 있는 방법이 있나요?

나는 세 가지 해결책을 고려합니다.

  1. BOM 바이트를 직접 작성합니다. 예를 들어,

    gawk 'BEGIN { pat = "^(\xef\xbb\xbf)?a.*" } $0 ~ pat { print }'
    

    UTF-8에서 작동합니다. 그러나 다른 인코딩은 처리하지 않습니다. 또한 너비가 0인 잘림 방지 공백으로 사용되는 U+FEFF가 있는 경우 위 스크립트가 실패하는 경우도 있습니다(설명 참조).

  2. recoding을 사용하여 BOM 바이트를 제거합니다 nkf. 예를 들어,

    nkf --oc=UTF-8 list.bom.txt | gawk '/^a.*/'
    

    일하다. 그래도 좀 더 정교한 방법이 있는지 알고 싶습니다.

  3. [추가됨] 이는 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 ...

관련 정보