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:
-
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.
-
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.
-
[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.