Utilizzando awk per rimuovere il segno di ordine di byte
-
21-08-2019 - |
Domanda
Come direbbe un awk
scritto (presumibilmente un one-liner) per la rimozione di un BOM assomigliare?
Specification:
- stampa ogni linea dopo la prima (
NR > 1
) - per la prima riga: Se inizia con
#FE #FF
o#FF #FE
, rimuovere quelli e stampare il resto
Soluzione
Prova questo:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}{print}' INFILE > OUTFILE
Al primo record (riga), rimuovere i caratteri BOM. Stampa ogni record.
In alternativa leggermente più corta, con la consapevolezza che l'azione predefinita in awk è quello di stampare il record:
awk 'NR==1{sub(/^\xef\xbb\xbf/,"")}1' INFILE > OUTFILE
1
è la condizione più breve che restituisce sempre vero, così ogni record viene stampato.
Enjoy!
- ADDENDUM -
Unicode Byte Order Mark (BOM) FAQ include la seguente tabella che elenca l'esatto BOM byte per ogni codifica:
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
In questo modo, si può vedere come \xef\xbb\xbf
corrisponde a EF BB BF
UTF-8
BOM byte dalla tabella di cui sopra.
Altri suggerimenti
Uso GNU sed
(su Linux o Cygwin):
# Removing BOM from all text files in current directory:
sed -i '1 s/^\xef\xbb\xbf//' *.txt
In FreeBSD:
sed -i .bak '1 s/^\xef\xbb\xbf//' *.txt
Il vantaggio di utilizzare GNU o FreeBSD -i
: il parametro di awk
significa "a posto", e aggiornerà i file senza la necessità di reindirizzamenti o trucchi strani
Su Mac:
Questa soluzione \xef
in un'altra risposta funziona , ma il comando sponge
sopra non funziona. Almeno su Mac (Sierra) <=> documentazione non riporta sostenere esadecimale sfuggire ala <=>.
Un trucco simile può essere ottenuto con qualsiasi programma dalla tubazione all'utensile <=> da moreutils :
awk '…' INFILE | sponge INFILE
Non awk, ma più semplice:
tail -c +4 UTF8 > UTF8.nobom
Per verificare la presenza di BOM:
hd -n 3 UTF8
Se BOM è presente vedrete: 00000000 ef bb bf ...
Oltre a convertire i fine riga CRLF a LF, dos2unix
rimuove anche le distinte base:
dos2unix *.txt
<=> converte anche UTF-16 file con una distinta base (ma non i file senza un BOM UTF-16) a UTF-8 senza 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
So che la domanda era rivolta a Unix / Linux, pensato che varrebbe la pena di menzionare una buona opzione per l'unix-sfidato (su Windows, con un'interfaccia utente).
Ho incontrato lo stesso problema in un progetto di WordPress (BOM stava causando problemi con feed rss e convalida pagina) e ho dovuto guardare in tutti i file in una abbastanza grande albero di directory per trovare quello che era con BOM. Trovato un'applicazione chiamata Sostituire Pioneer e in esso:
Batch Runner -> Ricerca (per trovare tutti i file nelle sottocartelle) -> Sostituire Template -> Binary rimuovere BOM (v'è una ricerca fatta pronta e sostituire modello per questo).
Non era la soluzione più elegante ed ha richiesto l'installazione di un programma, che è un aspetto negativo. Ma una volta che ho scoperto quello che stava succedendo intorno a me, ha funzionato come un fascino (e ha trovato 3 file su circa 2300 che erano con BOM).