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
È stato utile?

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).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top