Usando awk para remover a marca de ordem de byte
-
21-08-2019 - |
Pergunta
Como é que um script awk
(presumivelmente um one-liner) para a remoção de um olhar BOM como ?
Especificação:
- imprimir cada linha após a primeira (
NR > 1
) - para a primeira linha: Se ele começa com
#FE #FF
ou#FF #FE
, remover aqueles e imprimir o resto
Solução
Tente isto:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE
No primeiro registro (linha), remova os caracteres BOM. Imprimir cada registro.
Ou um pouco mais curto, usando o conhecimento de que a ação padrão em awk é imprimir o registro:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE
1
é a condição mais curto que sempre avalia a verdade, de modo que cada registro é impresso.
Aproveite!
- ADENDO -
Unicode Byte Order Mark (BOM) FAQ inclui o seguinte tabela listando o BOM exata bytes 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 corresponde \xef\xbb\xbf
para EF BB BF
UTF-8
BOM bytes da tabela acima.
Outras dicas
Usando 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 GNU ou sed
FreeBSD:. Os meios de parâmetros -i
"no lugar", e irá atualizar 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 (Serra) documentação sed
não menciona apoio hexadecimal escapar ala \xef
.
Um truque semelhante pode ser alcançado com qualquer programa, canalizando para a ferramenta sponge
de moreutils :
awk '…' INFILE | sponge INFILE
Não awk, mas mais simples:
tail -c +4 UTF8 > UTF8.nobom
Para verificar se há BOM:
hd -n 3 UTF8
Se BOM está presente você verá: 00000000 ef bb bf ...
Além de converter finais de linha CRLF para LF, dos2unix
também remove BOMs:
dos2unix *.txt
dos2unix
também converte UTF-16 arquivos com um BOM (mas não UTF-16 arquivos sem BOM) para UTF-8 sem 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 pergunta era dirigida a unix / linux, pensei que seria interessante mencionar uma boa opção para o unix-desafiado (no Windows, com uma UI).
Corri para o mesmo problema em um projeto WordPress (BOM estava causando problemas com a alimentação de RSS e validação da página) e eu tive que olhar para todos os arquivos em uma árvore de diretórios muito grande para encontrar o que estava com BOM. Encontrou um aplicativo chamado Substituir Pioneer e nele:
Batch Runner -> Search (para encontrar todos os arquivos nas subpastas) -> Substituir Modelo -> BOM Binary remove (há um pronto-procurar e substituir modelo para isso).
Não era a solução mais elegante e que exigia a instalação de um programa, que é uma desvantagem. Mas uma vez que eu descobri o que estava acontecendo ao meu redor, ele trabalhou como um encanto (e encontrou 3 arquivos de cerca de 2300 que estavam com BOM).