AWK com BOM: Existe alguma maneira legal de lidar com Unicode BOM com regexp?

6

Eu tenho dois arquivos codificados em UTF-8 com / sem 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

A única diferença entre dois arquivos é o cabeçalho BOM EF BB BF .

Depois, para filtrar as linhas que começam com 'a', escrevo um pequeno script awk usando um acento circunflexo.

/tmp/bom$ gawk '/^a.*/' list.nobom.txt
apple
avocado
/tmp/bom$ gawk '/^a.*/' list.bom.txt
avocado

Infelizmente, com o BOM do cabeçalho, apple na primeira linha é ignorado.

Portanto, minha pergunta é: Existe alguma maneira de lidar com isso?

Eu considero três soluções:

  1. Grave bytes de BOM diretamente. Por exemplo,

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

    funciona em UTF-8. No entanto, isso não lida com outras codificações. Além disso, se houver U + FEFF usado como Espaço sem quebra de largura zero (ver comentários), o script acima falhará em alguns casos.

  2. Exclua os bytes da lista de materiais recodificando com nkf . Por exemplo,

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

    funciona. No entanto, gostaria de saber se existe uma maneira mais sofisticada.

  3. [ADICIONADO] Isso é uma melhoria do primeiro, usando o recurso bash.

    gawk -v bom="$(echo -e '\uFEFF')" '
        NR == 1 {
            pat = "^" bom;
            sub(pat, "")
        }
        /^a.*/ {
            print
        }
    '
    

    Isso funciona para ambos os UTF-8 com / sem BOM. No entanto, isso não funciona para o UTF-16 no meu ambiente. Então, a segunda solução é melhor.

Além disso, acho que esse também é o problema para grep , sed ou outros scripts que usam correspondência de expressão regular. Então, se houver uma solução geral, seria mais apreciado.

    
por nekketsuuu 20.01.2017 / 10:56

1 resposta

3

Uma lista de materiais não faz sentido em UTF-8. Esses são geralmente adicionados por engano por software falso em sistemas operacionais da Microsoft.

dos2unix irá removê-lo e também cuidará de outras idiossincrasias dos arquivos de texto do Windows.

dos2unix < file.win.txt | awk ...
    
por 20.01.2017 / 18:34