regex {} - ¿Cómo grep para todos los caracteres que no son ASCII?




linux con (9)

Curiosamente, tuve que hacer esto hoy! Terminé usando Perl porque no podía hacer que grep / egrep funcionara (incluso en el modo -P). Algo como:

cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'

Para caracteres Unicode (como \u2212 en el ejemplo a continuación) use esto:

find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;

Tengo varios archivos XML muy grandes y estoy tratando de encontrar las líneas que contienen caracteres que no son ASCII. He intentado lo siguiente:

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

Pero esto devuelve todas las líneas del archivo, independientemente de si la línea contiene un carácter en el rango especificado.

¿Tengo la sintaxis incorrecta o estoy haciendo otra cosa mal? También he intentado:

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(con comillas simples y dobles alrededor del patrón).


Buscando caracteres no imprimibles.

Estoy de acuerdo con Harvey anteriormente enterrado en los comentarios, a menudo es más útil buscar caracteres no imprimibles O es fácil pensar que no es ASCII cuando realmente debería estar pensando que no se puede imprimir. Harvey sugiere "usar esto:" [^ \ n - ~] ". Agregar \ r para archivos de texto DOS. Eso se traduce como" [^ \ x0A \ x020- \ x07E] "y agregar \ x0D para CR"

Además, agregar -c (mostrar el recuento de patrones coincidentes) a grep es útil cuando se buscan caracteres no imprimibles, ya que las cadenas coincidentes pueden desordenar el terminal.

Descubrí que agregar un rango de 0-8 y 0x0e-0x1f (al rango de 0x80-0xff) es un patrón útil. Esto excluye la TAB, CR y LF y uno o dos caracteres imprimibles poco comunes. Entonces, en mi humilde opinión, un patrón de grep bastante útil (aunque crudo) es ESTE:

grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *

Descompostura:

\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - perl style regexps

Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches

Por ejemplo, un ejemplo práctico de uso, encontrar para grep todos los archivos en el directorio actual:

find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} + 

Es posible que desee ajustar el grep a veces. por ejemplo, el carácter BS (0x08 - retroceso) utilizado en algunos archivos imprimibles o para excluir VT (0x0B - pestaña vertical). Los caracteres BEL (0x07) y ESC (0x1B) también pueden considerarse imprimibles en algunos casos.

Non-Printable ASCII Chars
** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes
Dec   Hex Ctrl Char description           Dec Hex Ctrl Char description
0     00  ^@  NULL                        16  10  ^P  DATA LINK ESCAPE (DLE)
1     01  ^A  START OF HEADING (SOH)      17  11  ^Q  DEVICE CONTROL 1 (DC1)
2     02  ^B  START OF TEXT (STX)         18  12  ^R  DEVICE CONTROL 2 (DC2)
3     03  ^C  END OF TEXT (ETX)           19  13  ^S  DEVICE CONTROL 3 (DC3)
4     04  ^D  END OF TRANSMISSION (EOT)   20  14  ^T  DEVICE CONTROL 4 (DC4)
5     05  ^E  END OF QUERY (ENQ)          21  15  ^U  NEGATIVE ACKNOWLEDGEMENT (NAK)
6     06  ^F  ACKNOWLEDGE (ACK)           22  16  ^V  SYNCHRONIZE (SYN)
7     07  ^G  BEEP (BEL)                  23  17  ^W  END OF TRANSMISSION BLOCK (ETB)
8     08  ^H  BACKSPACE (BS)**            24  18  ^X  CANCEL (CAN)
9     09  ^I  HORIZONTAL TAB (HT)**       25  19  ^Y  END OF MEDIUM (EM)
10    0A  ^J  LINE FEED (LF)**            26  1A  ^Z  SUBSTITUTE (SUB)
11    0B  ^K  VERTICAL TAB (VT)**         27  1B  ^[  ESCAPE (ESC)
12    0C  ^L  FF (FORM FEED)**            28  1C  ^\  FILE SEPARATOR (FS) RIGHT ARROW
13    0D  ^M  CR (CARRIAGE RETURN)**      29  1D  ^]  GROUP SEPARATOR (GS) LEFT ARROW
14    0E  ^N  SO (SHIFT OUT)              30  1E  ^^  RECORD SEPARATOR (RS) UP ARROW
15    0F  ^O  SI (SHIFT IN)               31  1F  ^_  UNIT SEPARATOR (US) DOWN ARROW

En perl

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile

Los siguientes trabajos para mí:

grep -P "[\x80-\xFF]" file.xml

Los caracteres no ASCII comienzan en 0x80 y van a 0xFF cuando se miran los bytes. Grep (y la familia) no realizan el procesamiento Unicode para combinar caracteres de múltiples bytes en una sola entidad para la coincidencia de expresiones regulares como pareces querer. La opción -P en mi grep permite el uso de escapes de \xdd en clases de caracteres para lograr lo que deseas.


Aquí hay otra variante que encontré que produjo resultados completamente diferentes de la búsqueda de grep para [\x80-\xFF] en la respuesta aceptada. Quizás le sea útil a alguien encontrar caracteres adicionales que no sean ascii:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

Nota: el grep de mi computadora (una Mac) no tenía la opción -P , así que ggrep brew install grep e inicié la llamada anterior con ggrep lugar de grep .


La forma más fácil es definir un carácter no ASCII ... como un carácter que no es un carácter ASCII.

LC_ALL=C grep '[^ -~]' file.xml

Añadir una pestaña después de la ^ si es necesario.

La configuración de LC_COLLATE=C evita sorpresas desagradables sobre el significado de los rangos de caracteres en muchos lugares. El ajuste LC_CTYPE=C es necesario para hacer coincidir los caracteres de un solo byte; de ​​lo contrario, el comando perdería las secuencias de bytes no válidas en la codificación actual. La configuración de LC_ALL=C evita por completo los efectos dependientes de la configuración regional.


En lugar de hacer suposiciones sobre el rango de bytes de los caracteres que no son ASCII, como lo hacen la mayoría de las soluciones anteriores, es IMO un poco mejor ser explícito sobre el rango de bytes real de los caracteres ASCII.

Así que la primera solución, por ejemplo, sería:

grep --color='auto' -P -n '[^\x00-\x7F]' file.xml

(que básicamente codicia para cualquier carácter fuera del rango ASCII hexadecimal: desde \ x00 hasta \ x7F)

En Mountain Lion eso no funcionará (debido a la falta de soporte de PCRE en BSD grep) , pero con pcre instalado a través de Homebrew, lo siguiente funcionará igual de bien:

pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml

¿Alguna ventaja o desventaja que alguien pueda pensar?


Podría ser interesante saber cómo buscar un personaje Unicode. Este comando puede ayudar. Solo necesitas conocer el código en UTF8.

grep -v $'\u200d'

En mi caso, necesitaba buscar un Compromiso corto y las soluciones enumeradas no funcionaban.

Logré hacerlo con: (reemplazar el token REGEX )

for commit in $(git rev-list --all --abbrev-commit)
do
    if [[ $commit =~ __REGEX__ ]]; then 
        git --no-pager show -s --format='%h %an - %s' $commit
    fi
done




regex unix unicode grep