2010-01-23 16 views
127

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

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

+2

está instalado perl? –

+1

Paul, sí puedo usar perl – Rory

Respuesta

221

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

[^\x00-\x7F] 

Ésta es una válida PCRE (Compatibles con Perl expresiones regulares).

También puede utilizar los POSIX abreviaturas:

  • [[:ascii:]] - coincide con un single-char ASCII
  • [^[:ascii:]] - coincide con una sola carbón no ASCII

[^[:print:]] será suficiente probablemente para ti. **

+0

¿no es así? [~ \ X20- \ x7f] – adrianm

+2

@adrianm: No, '^' es válido en PCRE. –

+10

Eso es exactamente correcto. Sin embargo, debe usar pcregrep, no grep estándar. [^ [: print:]] no funcionará si su terminal está configurada en UTF8. – Rory

4

También puede consultar esta página: Unicode Regular Expressions, ya que contiene algunas clases útiles caracteres Unicode, como:

\p{Control}: an ASCII 0x00..0x1F or Latin-1 0x80..0x9F control character.
+0

[grep estándar no es compatible con esos] (https://www.gnu.org/software/grep/manual/grep.html). – eis

1

Usted realmente no necesita una expresión regular.

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

Esto mostrará nombres de archivo con caracteres de control en sus nombres, también, pero considero que es una función.

Si no tiene ningún archivo que coincida, el glob se expandirá a nada.

+1

Curiosamente, esto no funciona correctamente en Bash. – tripleee

26

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

Esto es real ASCII:

[^\x00-\x7F] 

lo contrario, será recortar los saltos de línea y otros caracteres especiales que forman parte de la tabla ASCII!

0

Se puede utilizar esta expresión regular:

[^\w \xC0-\xFF] 

Caso preguntar, las opciones es Multilínea.

0

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 preprocesamiento de elementos que eventualmente se convertirán en claves hash.

1

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

Cuestiones relacionadas