Usando o awk para remover a marca de ordem de byte

Como seria um script awk (presumivelmente um one-liner) para remover uma BOM ?

Especificação:

  • imprimir todas as linhas após o primeiro ( NR > 1 )
  • para a primeira linha: Se começar com #FE #FF ou #FF #FE , remova-os e imprima o resto

Tente isto:

 awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE 

No primeiro registro (linha), remova os caracteres da lista de materiais. Imprima todos os registros.

Ou um pouco mais curto, usando o conhecimento de que a ação padrão no awk é imprimir o registro:

 awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE 

1 é a condição mais curta que sempre é avaliada como verdadeira, portanto, cada registro é impresso.

Apreciar!

— TERMO ADITIVO —

A FAQ da Marca de Ordem de Byte Unicode (BOM) inclui a seguinte tabela listando os bytes de BOM exatos para cada codificação:

 Bytes | Encoding Form -------------------------------------- 00 00 FE FF | UTF-32, big-endian FF FE 00 00 | UTF-32, little-endian FE FF | UTF-16, big-endian FF FE | UTF-16, little-endian EF BB BF | UTF-8 

Assim, você pode ver como \xef\xbb\xbf corresponde aos bytes de BOM UTF-8 EF BB BF da tabela acima.

Usando o GNU sed (no Linux ou Cygwin):

 # Removing BOM from all text files in current directory: sed -i '1 s/^\xef\xbb\xbf//' *.txt 

No FreeBSD:

 sed -i .bak '1 s/^\xef\xbb\xbf//' *.txt 

Vantagem de usar o GNU ou o FreeBSD sed : o parâmetro -i significa “no local” e atualizará os arquivos sem a necessidade de redirecionamentos ou truques estranhos.

No Mac:

Esta solução awk em outra resposta funciona , mas o comando sed acima não funciona. Pelo menos no Mac (Sierra), a documentação do sed não menciona o suporte ao escape hexadecimal de ala \xef .

Um truque similar pode ser alcançado com qualquer programa, canalizando a ferramenta sponge de moreutils :

 awk '…' INFILE | sponge INFILE 

Não awk, mas mais simples:

 tail -c +4 UTF8 > UTF8.nobom 

Para verificar a lista de materiais:

 hd -n 3 UTF8 

Se a lista de materiais estiver presente, você verá: 00000000 ef bb bf ...

Além de converter finais de linha CRLF para LF, o dos2unix também remove as BOMs:

 dos2unix *.txt 

dos2unix também converte arquivos UTF-16 com uma BOM (mas não com arquivos UTF-16 sem uma BOM) para UTF-8 sem uma BOM:

 $ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16be>bom-utf16be $ printf '\ufeffä\n'|iconv -f utf-8 -t utf-16le>bom-utf16le $ printf '\ufeffä\n'>bom-utf8 $ printf 'ä\n'|iconv -f utf-8 -t utf-16be>utf16be $ printf 'ä\n'|iconv -f utf-8 -t utf-16le>utf16le $ printf 'ä\n'>utf8 $ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done bom-utf16be feff00e4000a bom-utf16le fffee4000a00 bom-utf8 efbbbfc3a40a utf16be 00e4000a utf16le e4000a00 utf8 c3a40a $ dos2unix -q * $ for f in *;do printf '%11s %s\n' $f $(xxd -p $f);done bom-utf16be c3a40a bom-utf16le c3a40a bom-utf8 c3a40a utf16be 00e4000a utf16le e4000a00 utf8 c3a40a 

Eu sei que a questão foi direcionada ao unix / linux, achei que valeria a pena mencionar uma boa opção para o unix-challenged (no windows, com uma interface do usuário).
Eu me deparei com o mesmo problema em um projeto WordPress (BOM estava causando problemas com RSS feed e validação de página) e eu tive que olhar em todos os arquivos em uma tree de diretório bastante grande para encontrar o que estava com o BOM. Encontrou um aplicativo chamado Replace Pioneer e nele:

Batch Runner -> Search (para encontrar todos os arquivos nas subpastas) -> Substituir Template -> Binary remove BOM (existe um template de pesquisa e substituição pronto para isso).

Não foi a solução mais elegante e exigiu a instalação de um programa, o que é uma desvantagem. Mas uma vez eu descobri o que estava acontecendo ao meu redor, funcionou como um encanto (e encontrei 3 arquivos de cerca de 2300 que estavam com o BOM).