Processar arquivos Unicode com BOM corretamente com ferramentas POSIX

0

Tentando usar grep hoje, me deparei com o problema familiar do Byte Order Mark (BOM) em um arquivo Unicode (UTF-8, neste caso). Especificamente, eu estava tentando encontrar um arquivo começando com XYZ com o padrão grep '^XYZ' , mas é claro que grep tratou a BOM como três caracteres separados e não correspondeu à primeira linha do arquivo se a primeira linha começou com %código%. Eu até tentei atualizar a expressão regular para ignorar espaços ( XYZ ), mas sem sucesso.

Outras questões trataram da conversão de arquivos ou visando especificamente a BOM , mas eu quero saber se as ferramentas POSIX possuem uma opção geral para manipular arquivos Unicode corretamente. Se '^[[:space:]]*XYZ' manipulasse o arquivo Unicode corretamente, ele consideraria o conteúdo do arquivo iniciado após a BOM e corresponderia a grep na primeira linha como qualquer outra linha.

    
por palswim 03.01.2018 / 00:56

2 respostas

0

De outra resposta , parece que eu estava lidando com arquivos com uma assinatura de lista de materiais imprópria.

Assim, a resposta é que as ferramentas POSIX lidam com arquivos Unicode (UTF-8) corretamente.

Se você tem um Unicode ruim, é claro que eles não funcionam corretamente, mas você pode usar a segmentação de BOMs de outras perguntas lidar com assinaturas de listas de materiais supérfluas.

    
por 11.02.2018 / 01:18
4

O Unicode Consortium tem uma FAQ que inclui Como devo lidar com listas de materiais . Esta parte inclui:

Where a text data stream is known to be plain Unicode text (but not which endian), then BOM can be used as a signature. If there is no BOM, the text should be interpreted as big-endian.

e

Where the precise type of the data stream is known (e.g. Unicode big-endian or Unicode little-endian), the BOM should not be used. In particular, whenever a data stream is declared to be UTF-16BE, UTF-16LE, UTF-32BE or UTF-32LE a BOM must not be used.

Note que o UTF-8 é sempre de endianness conhecido, porque não tem endianness. Portanto, contanto que você saiba que o texto é UTF-8, "a BOM não deve ser usada".

Mesmo cat retornará resultados incorretos ao usar um BOM desnecessariamente, já que os BOMs de todos os arquivos, mas o primeiro, serão tratados como espaços sem quebra de largura zero. Mas o poder do UNIX está nos filtros.

Para operações em um único arquivo ou fluxo, sed "1s/^$(printf '737')//" em um pipeline removerá uma BOM se presente, deixando todos os outros fluxos intactos.

Para operações com vários arquivos, um shell com substituição de processo (como o Bash, mas infelizmente não o shell POSIX) é útil:

sb() { sed "1s/$(printf '737')//" "$@" ; }
cat <(sb file1) <(sb file2) …
    
por 03.01.2018 / 06:09