Uso de awk para eliminar la marca de orden de bytes


¿Cómo se vería un script awk (presumiblemente de una sola línea) para eliminar un BOM ?

Especificación:

  • imprima cada línea después de la primera (NR > 1)
  • para la primera línea: Si comienza con #FE #FF o #FF #FE, elimínelas e imprima el resto
Author: Boldewyn, 2009-07-01

5 answers

Prueba esto:

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

En el primer registro (línea), elimine los caracteres de la lista de materiales. Imprime cada disco.

O un poco más corto, usando el conocimiento de que la acción predeterminada en awk es imprimir el registro:

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

1 es la condición más corta que siempre se evalúa a verdadero, por lo que se imprime cada registro.

Disfrute!

-- ADICIÓN {

Unicode Byte Order Mark (BOM) FAQ incluye la siguiente tabla con una lista de los bytes exactos de la BOM para cada codificación:

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

Por lo tanto, se puede ver cómo \xef\xbb\xbf corresponde a EF BB BF UTF-8 BOM bytes de la tabla anterior.

 107
Author: Bartosz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 16:00:48

Usando GNU sed (en Linux o Cygwin):

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

En FreeBSD:

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

Ventaja de usar GNU o FreeBSD sed: el parámetro -i significa "en su lugar", y actualizará los archivos sin necesidad de redirecciones o trucos extraños.

En Mac:

Esta solución awk en otra respuesta funciona, pero el comando sed anterior no funciona. Al menos en Mac (Sierra) sed la documentación no menciona el soporte de escape hexadecimal ala \xef.

Un truco similar se puede lograr con cualquier programa mediante la tubería a la herramienta sponge de moreutils :

awk '…' INFILE | sponge INFILE
 121
Author: Denilson Sá Maia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-08 09:03:38

No awk, pero más simple:

tail -c +4 UTF8 > UTF8.nobom

Para comprobar la lista de materiales:

hd -n 3 UTF8

Si BOM está presente, verás: 00000000 ef bb bf ...

 40
Author: Steve Clay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-15 20:07:07

Además de convertir los finales de línea CRLF a LF, dos2unix también elimina las listas de materiales:

dos2unix *.txt

dos2unix también convierte archivos UTF-16 con una lista de materiales (pero no archivos UTF-16 sin una lista de materiales) a UTF-8 sin una lista de materiales:

$ 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
 19
Author: user495470,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-29 12:43:57

Sé que la pregunta estaba dirigida a unix/linux, pensé que valdría la pena mencionar una buena opción para los unix desafiados (en Windows, con una interfaz de usuario).
Me encontré con el mismo problema en un proyecto de WordPress (BOM estaba causando problemas con el feed rss y la validación de la página) y tuve que buscar en todos los archivos en un árbol de directorios bastante grande para encontrar el que estaba con BOM. Encontré una aplicación llamada Replace Pioneer y en ella:

Batch Runner - > Buscar (para encontrar todos los archivos en las subcarpetas) - > Reemplazar plantilla - > Eliminar Binario BOM (hay una búsqueda ya hecha y reemplazar plantilla para esto).

No era la solución más elegante y requería instalar un programa, lo cual es un inconveniente. Pero una vez que descubrí lo que estaba pasando a mi alrededor, funcionó como un encanto (y encontré 3 archivos de unos 2300 que estaban con BOM).

 2
Author: Arnon Zamir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-21 10:20:33