Comment spécifier des caractères en utilisant des codes hexadécimaux dans `grep`?

27

J'utilise la commande suivante pour grep plage de jeux de caractères pour le code hexadécimal 0900 (au lieu de अ) à 097F (au lieu de व). Comment puis-je utiliser du code hexadécimal à la place de अ et व?

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

J'obtiens la sortie suivante:

    <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> 
    ...

Je veux juste utiliser du code hexadécimal au lieu de अ et व dans la commande ci-dessus.

Si l'utilisation du code hexadécimal n'est pas du tout possible, puis-je utiliser unicode au lieu du code hexadécimal pour le jeu de caractères ('अ-व')?

J'utilise Ubuntu 10.04

Dhrubo Bhattacharjee
la source
1
Que voulez-vous dire "ne fonctionne pas"? -vInverse également la correspondance, à partir du texte de votre question, il semble que ce ne soit pas ce que vous voulez.
Christian.K
@ Christian.K Désolé pour le retard ... J'ai édité la question, veuillez jeter un œil.
J'attends toujours une réponse appropriée. :(
Dhrubo Bhattacharjee

Réponses:

21

Regardez cette question .

Le texte est généralement codé en UTF-8; vous devez donc utiliser les valeurs hexadécimales des octets utilisés dans le codage utf-8.

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

et

grep '[अ-व]'

sont équivalents, et ils effectuent une correspondance basée sur les paramètres régionaux (c'est-à-dire que la correspondance dépend des règles de tri du script devanagari (c'est-à-dire que la correspondance n'est PAS "un caractère entre \ u0905 et \ 0935") mais plutôt "tout tri entre devanagari" A et devanagari VA "; il peut y avoir des différences.

En revanche, vous avez ceci (note -P):

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

qui fera une correspondance binaire avec ces valeurs d' octets .

Pablo Saratxaga
la source
2
Veuillez expliquer le préfixe "["$'et le suffixe"]"
Jonathan Komar
6

Si l'échappement du shell est suffisant, vous pouvez utiliser la $'\xHH'syntaxe comme ceci:

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

Est-ce suffisant pour votre cas d'utilisation?

Stéphane Gimenez
la source
echo 'अ-व' | hdme donnee0 a4 85 - e0 a4 b5
enzotib
En effet, l'OP a donné des valeurs unicode, pas des vidages hexadécimaux dans le codage UTF-8: - / Étant donné qu'il grepn'est lié à aucune lib, je suppose qu'il n'est pas possible de faire effectuer la conversion de plage par grep: - /
Stéphane Gimenez
1
Btw, zshest capable d'interpréter "\u0900"et "\u097F", mais le comportement dépendra de la plage codée UTF-8 étant continue (c'est probablement le cas).
Stéphane Gimenez
Aucun grep -v "<[" $ '\ x09 \ x00' "-" $ '\ x09 \ x7F' "] * \ s" donne la sortie suivante <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> .... Ce n'est pas prévu. :(, Puis-je utiliser unicode au lieu du code hexadécimal ou du jeu de caractères ('अ-व')?
Dhrubo Bhattacharjee
6

La valeur "hexadécimale" que 0x0900vous avez écrite est exactement la valeur du point de code UNICODE qui est également en hexadécimal.

code hexadécimal 0900 (au lieu de अ)

Je crois que ce que vous voulez dire est le hexadécimal point de code UNICODE: U0905.

Le caractère U-0900 est pas celui que vous utilisez: .
Ce caractère est U0905 , faisant partie de cette page Unicode , ou répertorié sur cette page .

Dans bash(installé par défaut dans Ubuntu), ou directement avec le programme à: /usr/bin/printf(mais pas avec shprintf), un caractère Unicode pourrait être produit avec:

$ printf '\u0905'

$ /usr/bin/printf '\u0905'

Cependant, ce caractère, qui provient d'un numéro de point de code, pourrait être représenté par plusieurs flux d'octets en fonction de la page de code utilisée.
Il devrait être évident que \U0905c'est 0x09 0x05en UTF-16 (UCS-2, etc.)
et 0x00 0x00 0x09 0x05en UTF-32.
Ce n'est peut-être pas évident, mais dans utf-8, il est représenté par 0xe0 0xa4 0x85:

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

Si les paramètres régionaux de votre console sont similaires en_US.UTF-8.

Et je parle du shell parce que c'est celui qui transforme une chaîne en ce que l'application reçoit. Cette:

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

fait grep "voir" le caractère dont vous avez besoin.
Pour comprendre la ligne ci-dessus, vous pouvez utiliser l'écho:

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

Ensuite, nous pouvons construire une plage de caractères, comme vous le demandez:

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

Cela répond à votre question:

Comment puis-je utiliser du code hexadécimal à la place de अ et व?

Sorontar
la source
C'est de loin la meilleure réponse --- elle aborde clairement le problème des représentations des points unicode dans le shell et montre comment aller et venir entre ces codes hexadécimaux.
Stefano
2

nous voulions convertir les guillemets ouverts non ascii et fermer les guillemets doubles en guillemets doubles normaux ("). De même, le guillemet simple non ascii en guillemets simples réguliers (').

pour les voir dans le fichier (ubuntu bash shell):

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

les traduire:

$ /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
Gaius Gracchus
la source