(grep) Regex para que coincida con caracteres no ASCII?

169

En Linux, tengo un directorio con muchos archivos. Algunos de ellos tienen caracteres no ASCII, pero todos son UTF-8 válidos . Un programa tiene un error que impide que funcione con nombres de archivo que no son ASCII, y tengo que averiguar cuántos están afectados. Iba a hacer esto findy luego hacer un grep para imprimir los caracteres que no son ASCII, y luego hacer un wc -lpara encontrar el número. No tiene que ser grep; Puedo usar cualquier expresión regular estándar de Unix , como Perl , sed , AWK , etc.

Sin embargo, ¿hay una expresión regular para 'cualquier carácter que no sea un carácter ASCII'?

Rory
fuente
1
Paul, sí, puedo usar Perl
Rory
/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]
Tinmarino

Respuestas:

310

Esto coincidirá con un solo carácter no ASCII:

[^\x00-\x7F]

Esta es una PCRE ( expresión regular compatible con Perl) válida .

También puedes usar las manos cortas POSIX :

  • [[:ascii:]] - coincide con un solo carácter ASCII
  • [^[:ascii:]] - coincide con un solo carácter no ASCII

[^[:print:]] probablemente sea suficiente para ti. **

Alix Axel
fuente
3
@adrianm: No, ^es válido en PCRE.
Alix Axel el
10
Eso es exactamente correcto. Sin embargo, debe usar pcregrep, no grep estándar. [^ [: print:]] no funcionará si su terminal está configurado en UTF8.
Rory
@Rory, ¿por qué :print:no funcionará en un terminal UTF8? Esto funciona para mí en palanca en una terminal UTF8:27.chr =~ /[^[:print:]]/
akostadinov
Esto es realmente bueno para arreglar nombres de archivos incorrectos rename 's/[^\x00-\x7F]//g' *(puede usar -npara verificar que los cambios de nombre estén bien primero).
naught101
¿Cómo hago coincidir cualquier carácter que no sea UTF8 y otros caracteres específicos?
CMCDragonkai
37

No, [^\x20-\x7E]no es ASCII.

Esto es ASCII real:

 [^\x00-\x7F]

De lo contrario, recortará nuevas líneas y otros caracteres especiales que forman parte de la tabla ASCII.

Peter L
fuente
3

[^\x00-\x7F]y [^[:ascii:]]perder algunos bytes de control para que las cadenas puedan ser la mejor opción a veces. Por ejemplo cat test.torrent | perl -pe 's/[^[:ascii:]]+/\n/g', hará cosas extrañas en su terminal, donde strings test.torrentse comportará como.

usuario1133275
fuente
3

Para validar el cuadro de texto Aceptar Ascii Use solo este patrón

[\x00-\x7F]+

Othman Mahmoud
fuente
3

Yo uso [^\t\r\n\x20-\x7E]+y eso parece estar funcionando bien.

SolidSnakeUk89
fuente
2

Puedes usar esta expresión regular:

[^\w \xC0-\xFF]

Caso pregunte, las opciones son Multilínea .

Patata Cifrada
fuente
2

Realmente no necesitas una expresión regular.

printf "%s\n" *[!\ -~]*

Esto también mostrará nombres de archivos con caracteres de control en sus nombres, pero considero que es una característica.

Si no tiene ningún archivo coincidente, el globo se expandirá solo, a menos que lo haya nullglobconfigurado. (La expresión no coincide, por lo que técnicamente, esta salida no es ambigua).

tripleee
fuente
Con retraso, puedo observar que esto hace el trabajo correctamente si en realidad tiene algunos archivos que se ajustan a este patrón. El comportamiento en el que el patrón se imprime cuando no hay coincidencias es un poco sorprendente, pero en realidad es correcto. Edité la respuesta para aclarar esto con suerte.
tripleee
1

Esto resultó ser muy flexible y extensible. $ campo = ~ s / [^ \ x00- \ x7F] // g; # por lo tanto, todos los elementos no ASCII o específicos en cuestión podrían limpiarse. Muy agradable ya sea en la selección o en el procesamiento previo de los elementos que eventualmente se convertirán en claves hash.

Don Turnblade
fuente