¿Cómo especificar caracteres usando códigos hexadecimales en `grep`?

27

Estoy usando el siguiente comando para grep rango de juego de caracteres para el código hexadecimal 0900 (en lugar de अ) a 097F (en lugar de व). ¿Cómo puedo usar el código hexadecimal en lugar de अ y व?

bzcat archive.bz2 | grep -v '<[अ-व]*\s' | tr '[:punct:][:blank:][:digit:]' '\n' | uniq | grep -o '^[अ-व]*$' | sort -f | uniq -c | sort -nr | head -50000 | awk '{print "<w f=\""$1"\">"$2"</w>"}' > hindi.xml

Me sale el siguiente resultado:

    <w f="399651">और</w>
    <w f="264423">एक</w>
    <w f="213707">पर</w>
    <w f="74728">कर</w>
    <w f="44281">तक</w>
    <w f="35125">कई</w>
    <w f="26628">द</w>
    <w f="23981">इन</w>
    <w f="22861">जब</w> 
    ...

Solo quiero usar código hexadecimal en lugar de अ y व en el comando anterior.

Si el uso del código hexadecimal no es posible, ¿puedo usar unicode en lugar del código hexadecimal para el juego de caracteres ('अ-व')?

Estoy usando Ubuntu 10.04

Dhrubo Bhattacharjee
fuente
1
¿Qué quieres decir con "no funciona"? También -vinvierte la coincidencia, de su texto de pregunta parece que no es lo que desea.
Christian.K
@ Christian.K Perdón por el retraso ... He editado la pregunta, por favor, eche un vistazo.
Todavía estoy esperando una respuesta adecuada. :(
Dhrubo Bhattacharjee

Respuestas:

21

Mira esta pregunta .

El texto generalmente está codificado en UTF-8; por lo que debe usar los valores hexadecimales de los bytes utilizados en la codificación utf-8.

grep "["$'\xe0\xa4\x85'"-"$'\xe0\xa4\xb5'"]"

y

grep '[अ-व]'

son equivalentes y realizan una coincidencia basada en la configuración regional (es decir, la coincidencia depende de las reglas de ordenación del script devanagari (es decir, la coincidencia NO es "ningún carácter entre \ u0905 y \ 0935", sino "cualquier cosa que se clasifique entre devanagari") A y devanagari VA "; puede haber diferencias.

Por otro lado, tienes esto (nota -P):

grep -P "\xe0\xa4[\x85-\xb5]"

eso hará una coincidencia binaria con esos valores de bytes .

Pablo Saratxaga
fuente
2
Por favor, explique el prefijo "["$'y el sufijo"]"
Jonathan Komar
6

Si el escape de shell es suficiente, puede usar la $'\xHH'sintaxis como esta:

grep -v "<["$'\x09\x00'"-"$'\x09\x7F'"]*\s"

¿Es eso suficiente para su caso de uso?

Stéphane Gimenez
fuente
echo 'अ-व' | hdme dae0 a4 85 - e0 a4 b5
enzotib
De hecho, el OP dio valores unicode, no volcados hexadecimales en la codificación UTF-8: - / Dado grepque no está vinculado con ninguna lib, supongo que no es posible que grep realice la conversión de rango: - /
Stéphane Gimenez
1
Por cierto, zshes capaz de interpretar "\u0900"y "\u097F", pero el comportamiento dependerá de que el rango codificado UTF-8 sea continuo (probablemente lo sea).
Stéphane Gimenez
No grep -v "<[" $ '\ x09 \ x00' "-" $ '\ x09 \ x7F' "] * \ s" da el siguiente resultado <wf = "16929"> x </w> <wf = " 10995 "> F </w> <wf =" 2548 "> FF </w> <wf =" 762 "> FFFFFF </w> <wf =" 655 "> FFFF </w> <wf =" 266 " > xx </w> <wf = "215"> FFF </w> <wf = "117"> xxx </w> .... Esto no se espera. :(, ¿Puedo usar unicode en lugar de código hexadecimal o juego de caracteres ('अ-व')?
Dhrubo Bhattacharjee
6

El valor "hexadecimal" 0x0900que escribió es exactamente el valor del punto de código UNICODE que también está en hexadecimal.

código hexadecimal 0900 (en lugar de अ)

Creo que lo que usted quiere decir es el punto de código Unicode hexadecimal: U0905.

El carácter en el T-0900 no es la misma que utilizó: .
Ese carácter es U0905 , parte de esta página Unicode , o aparece en esta página .

En bash(instalado de manera predeterminada en Ubuntu), o directamente con el programa en: /usr/bin/printf(pero no con shprintf), se podría generar un carácter Unicode con:

$ printf '\u0905'

$ /usr/bin/printf '\u0905'

Sin embargo, ese carácter, que proviene de un número de punto de código, podría estar representado por varias secuencias de bytes, dependiendo de la página de códigos utilizada.
Debería ser obvio que \U0905está 0x09 0x05en UTF-16 (UCS-2, etc.)
y 0x00 0x00 0x09 0x05en UTF-32.
Puede que no sea obvio, pero en utf-8 está representado por 0xe0 0xa4 0x85:

$ /usr/bin/printf '\u0905' | od -vAn -tx1
e0 a4 85

Si la configuración regional de su consola es algo similar a en_US.UTF-8.

Y estoy hablando del shell porque es el que transforma una cadena en lo que recibe la aplicación. Esta:

grep "$(printf '\u0905')" file

hace que grep "vea" el personaje que necesita.
Para comprender la línea anterior, puede usar echo:

$ echo grep "$(printf '\u0905')" file
grep  file

Luego, podemos construir un rango de caracteres, según lo solicite:

$ echo grep "$(printf '[\u0905-\u097f]')" file
grep [अ-ॿ] file

Eso responde a tu pregunta:

¿Cómo puedo usar el código hexadecimal en lugar de अ y व?

sorontar
fuente
Esta es, con mucho, la mejor respuesta: aborda claramente el problema de las representaciones de puntos Unicode en el shell y muestra cómo ir y venir entre ellos códigos hexadecimales.
stefano
2

queríamos convertir la comilla doble abierta y la comilla cerrada no ascii en comillas dobles regulares ("). También la comilla simple no ascii en comillas simples regulares (').

para verlos en el archivo (ubuntu bash shell):

$ grep -P "\x92" infile.txt  (single)
$ grep -P "\x93" infile.txt  (open double)
$ grep -P "\x94" infile.txt  (close double)

TRADUCELOS:

$ /bin/sed "s/\x92/'/g" a.txt > b.txt
$ /bin/sed 's/\x93/"/g' b.txt > c.txt
$ /bin/sed 's/\x94/"/g' c.txt > d.txt
Cayo Graco
fuente