TL; DR:
grep -axv '.*' out.txt
respuesta larga
Ambas respuestas actuales son extremadamente engañosas y básicamente erróneas.
Para probar, obtenga estos dos archivos (de un desarrollador muy reconocido: Markus Kuhn):
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-demo.txt
$ wget https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
Manifestación
El primero UTF-8-demo.txt
es un archivo diseñado para mostrar qué tan bien UTF-8 puede presentar muchos idiomas, matemáticas, braille y muchos otros tipos de caracteres útiles. Eche un vistazo con un editor de texto (que entienda utf-8) y verá muchos ejemplos y no �
.
La prueba que propone una respuesta: limitar el rango de caracteres a \x00-\x7F
rechazará casi todo dentro de este archivo.
Eso está muy mal y no eliminará ninguno �
ya que no hay ninguno en ese archivo .
El uso de la prueba recomendada en esa respuesta eliminará 72.5 %
el archivo:
$ grep -oP "[^\x00-\x7F]" UTF-8-demo.txt | tr -d '\n' | wc -c
10192
$ cat UTF-8-demo.txt | wc -c
14058
Eso es (para la mayoría de los propósitos prácticos) todo el archivo. Un archivo muy bien diseñado para mostrar caracteres perfectamente válidos.
Prueba
El segundo archivo está diseñado para probar varios casos límite para confirmar que los lectores utf-8 están haciendo un buen trabajo. Contiene muchos caracteres que harán que se muestre una ' '. Pero la otra recomendación de respuesta (la seleccionada) para usar file
falla gravemente con este archivo. Solo eliminar un byte cero ( \0
) (que técnicamente es ASCII válido) y un \x7f
byte (DEL - eliminar) (que también es claramente un carácter ASCII) hará que todo el archivo sea válido para el file
comando:
$ cat UTF-8-test.txt | tr -d '\0\177' > a.txt
$ file a.txt
a.txt: Non-ISO extended-ASCII text, with LF, NEL line terminators
No solo no file
puede detectar los muchos caracteres incorrectos, sino que tampoco puede detectar e informar que se trata de un archivo codificado UTF-8.
Y sí, file
es capaz de detectar e informar texto codificado en UTF-8:
$ echo "ééakjfhhjhfakjfhfhaéá" | file -
/dev/stdin: UTF-8 Unicode text
Además, file
no informa como ASCII la mayoría de los caracteres de control en el rango de 1 a 31. ( file
) informa algunos rangos como data
:
$ printf '%b' "$(printf '\\U%x' {1..6})" | file -
/dev/stdin: data
Otros como ASCII text
:
$ printf '%b' "$(printf '\\U%x' 7 {9..12})" | file -
/dev/stdin: ASCII text
Como el rango de caracteres imprimibles (con nuevas líneas):
$ printf '%b' "$(printf '\\U%x' {32..126} 10)" | file -
/dev/stdin: ASCII text
Pero algunos rangos pueden causar resultados extraños:
$ printf '%b' "$(printf '\\U%x' {14..26})" | file -
/dev/stdin: Atari MSA archive data, 4113 sectors per track, starting track: 5141, ending track: 5655
El programa file
no es una herramienta para detectar texto, sino para detectar números mágicos en programas o archivos ejecutables.
Los rangos file
detectados, y el tipo correspondiente informado que encontré fueron:
Valores de un byte, principalmente ascii:
{1..6} {14..26} {28..31} 127 :data
{128..132} {134..159} :Non-ISO extended-ASCII text
133 :ASCII text, with LF, NEL line terminators
27 :ASCII text, with escape sequences
13 :ASCII text, with CR, LF line terminators
8 :ASCII text, with overstriking
7 {9..12} {32..126} :ASCII text
{160..255} :ISO-8859 text
Rangos codificados Utf-8:
{1..6} {14..26} {28..31} 127 :data
27 :ASCII text, with escape sequences
13 :ASCII text, with CR, LF line terminators
8 :ASCII text, with overstriking
7 {9..12} {32..126} :ASCII text
{128..132} {134..159} :UTF-8 Unicode text
133 :UTF-8 Unicode text, with LF, NEL line terminators
{160..255} :UTF-8 Unicode text
{256..5120} :UTF-8 Unicode text
Una posible solución se encuentra a continuación.
Respuesta previa
El valor Unicode para el personaje que está publicando es:
$ printf '%x\n' "'�"
fffd
Sí, ese es un 'CARÁCTER DE REEMPLAZO' de caracteres Unicode (U + FFFD) . Ese es un carácter utilizado para reemplazar cualquier carácter Unicode no válido encontrado en el texto. Es una "ayuda visual", no un personaje real. Para buscar y enumerar todas las líneas completas que contienen caracteres UNICODE no válidos , use:
grep -axv '.*' out.txt
pero si solo desea detectar si algún carácter no es válido, use:
grep -qaxv '.*' out.txt; echo $?
Si el resultado es que 1
el archivo está limpio, de lo contrario será cero 0
.
Si lo que preguntabas era: cómo encontrar el �
personaje, entonces usa esto:
➤ a='Basically, if the file "out.txt" contains "�" anywhere in the file I'
➤ echo "$a" | grep -oP $(printf %b \\Ufffd)
�
O si su sistema procesa correctamente el texto UTF-8, simplemente:
➤ echo "$a" | grep -oP '�'
�
grep
Hace tiempo que entiende unicode (lo que lo hace mucho más lento, por lo que buscar cadenas ASCIILANG=C grep
es una gran mejora del rendimiento).