Usar awk para eliminar la marca de orden de bytes

¿Cómo sería una secuencia de comandos awk (presumiblemente una línea) para eliminar una lista de materiales ?

Especificación:

  • imprime cada línea después de la primera ( NR > 1 )
  • para la primera línea: si comienza con #FE #FF o #FF #FE , elimínelos e imprima el rest

Prueba esto:

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

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

O un poco más corto, con 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 como verdadera, por lo que cada registro se imprime.

¡Disfrutar!

– ADDENDUM –

Las preguntas frecuentes sobre la marca de orden de bytes Unicode (BOM) incluyen la siguiente tabla que enumera los bytes de BOM exactos para cada encoding:

 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, puede ver cómo \xef\xbb\xbf corresponde a los bytes de BOM EF BB BF UTF-8 de la tabla anterior.

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 utilizar GNU o FreeBSD sed : el parámetro -i significa “en su lugar” y actualizará los archivos sin necesidad de redirecciones ni trucos extraños.

En Mac:

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

Se puede lograr un truco similar con cualquier progtwig conectando a la herramienta de sponge de moreutils :

 awk '…' INFILE | sponge INFILE 

No es extraño, pero es más simple:

 tail -c +4 UTF8 > UTF8.nobom 

Para verificar la lista de materiales:

 hd -n 3 UTF8 

Si la lista de materiales está presente, verá: 00000000 ef bb bf ...

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

 dos2unix *.txt 

dos2unix también convierte los 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 

Sé que la pregunta fue dirigida a Unix / Linux, pensé que sería útil mencionar una buena opción para los desafiados de Unix (en Windows, con una IU).
Me encontré con el mismo problema en un proyecto de WordPress (BOM estaba causando problemas con la alimentación 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 la lista de materiales. Encontré una aplicación llamada Replace Pioneer y en ella:

Batch Runner -> Search (para buscar todos los archivos en las subcarpetas) -> Replace Template -> Binary remove BOM (hay una plantilla de búsqueda y reemplazo lista para esto).

No fue la solución más elegante y sí requirió la instalación de un progtwig, lo cual es un inconveniente. Pero una vez que descubrí lo que sucedía a mi alrededor, funcionó como un amuleto (y encontré 3 archivos de aproximadamente 2300 que estaban con BOM).