2009-07-01 11 views

Répondre

105

Essayez ce:

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

Sur le premier enregistrement (ligne), supprimez les caractères de la nomenclature. Imprimer chaque enregistrement.

ou légèrement plus courte, en utilisant les connaissances que l'action par défaut dans awk est d'imprimer l'enregistrement:

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

1 est la plus courte condition est toujours vraie, de sorte que chaque enregistrement est imprimé.

Profitez-en!

- ADDENDA -

Unicode Byte Order Mark (BOM) FAQ comprend le tableau suivant liste la nomenclature exacte octets pour chaque encodage:

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 

Ainsi, vous pouvez voir comment \xef\xbb\xbf correspond à EF BB BFUTF-8 BOM octets de le tableau ci-dessus.

+1

Il semble que le point au milieu de la sous-déclaration est trop (au moins, mon awk se plaint à ce sujet). A côté de cela, c'est exactement ce que j'ai cherché, merci! – Boldewyn

+4

Cette solution, cependant, fonctionne ** seulement ** pour les fichiers codés en UTF-8. Pour d'autres, comme UTF-16, voir Wikipedia pour la représentation de nomenclature correspondante: http://en.wikipedia.org/wiki/Byte_order_mark – Boldewyn

+0

Je suis d'accord avec le commentaire précédent; le point n'appartient pas au milieu de cette déclaration et fait de ce petit bout de code un exemple d'erreur de syntaxe awk. –

40

Non awk, mais plus simple:

tail -c +4 UTF8 > UTF8.nobom 

Pour vérifier la nomenclature:

hd -n 3 UTF8 

Si la nomenclature est présent, vous verrez: 00000000 ef bb bf ...

+0

Le tour de la queue est cool. Merci! – Boldewyn

+5

Les BOM sont de 2 octets pour UTF-16 et de 4 octets pour UTF-32, et bien sûr, n'ont rien à faire avec UTF-8 en premier lieu. – tchrist

+0

@tchrist: de wikipedia: "La norme Unicode autorise la nomenclature en UTF-8, mais ne nécessite pas ou ne recommande pas son utilisation.L'ordre des octets n'a aucune signification en UTF-8, donc en UTF-8 la nomenclature ne sert qu'à ** identifier ** un flux de texte ou un fichier au format UTF-8. " –

119

En utilisant GNU sed (sous Linux ou Cygwin):

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

sur FreeBSD:

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

avantage d'utiliser GNU ou FreeBSD sed: le paramètre -i signifie « en place », et mettra à jour les fichiers sans avoir besoin de trucs bizarres ou redirections.

Sur Mac:

This awk solution in another answer works, mais la commande sed ne fonctionne pas au-dessus. Au moins sur Mac (Sierra) sed la documentation ne mentionne pas supportant hexadécimal s'échappant ala \xef.

Une astuce similaire peut être obtenu avec un programme par une canalisation à l'outil sponge de moreutils:

awk '…' INFILE | sponge INFILE 
+5

J'ai essayé la deuxième commande avec précision sur Mac OS X et le résultat était "succès", mais la substitution ne s'est pas réellement produite. – Trejkaz

+0

Il convient de noter que ces commandes remplacent une séquence d'octets spécifique, qui est [l'un des octets de commande d'octets possibles] (http://en.wikipedia.org/wiki/Byte_order_mark#Representations_of_byte_order_marks_by_encoding). Votre fichier a peut-être une séquence de nomenclature différente. (Je ne peux pas aider autre que cela, car je n'ai pas de Mac) –

+3

Lorsque j'ai essayé la deuxième commande sur OS X sur un fichier qui utilisait 0xef 0xbb 0xbf comme BOM, il n'a pas fait la substitution. –

2

Je sais a dirigé la question à unix/linux, a pensé qu'il serait intéressant de mentionner une bonne option pour l'unix-contesté (sur Windows, avec une interface utilisateur).
J'ai rencontré le même problème sur un projet WordPress (BOM causait des problèmes avec le flux rss et la validation de page) et j'ai dû examiner tous les fichiers dans un arborescence assez grande pour trouver celui qui était avec BOM. Trouvé une application appelée Replace Pioneer et dans ce:

Batch Runner -> Rechercher (pour trouver tous les fichiers dans les sous-dossiers) -> Remplacer le modèle -> Binary remove BOM (il existe un modèle de recherche et de remplacement prêt pour cela) .

Ce n'était pas la solution la plus élégante et il a fallu installer un programme, ce qui est un inconvénient. Mais une fois que j'ai découvert ce qui se passait autour de moi, cela a fonctionné comme un charme (et j'ai trouvé 3 fichiers sur environ 2300 qui étaient avec BOM).

+1

Je suis tellement heureux quand j'ai trouvé votre solution, mais je n'ai pas le privilège d'installer le logiciel sur l'ordinateur de l'entreprise. J'ai pris beaucoup de temps aujourd'hui, jusqu'à ce que je trouve l'alternative: Utiliser Notepad ++ avec plugin PythonScript. http://superuser.com/questions/418515/how-to-find-all-files-in-directory-that-contain-utf-8-bom-byte-order-mark/914116#914116 Merci quand même! –

18

En plus de convertir les fins de ligne CRLF LF, dos2unix Enlève aussi BOM:

dos2unix *.txt 

dos2unix convertit également les fichiers UTF-16 avec une nomenclature (mais pas les fichiers UTF-16 sans une nomenclature) à UTF- 8 sans nomenclature:

$ 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