Como especificar caracteres usando códigos hexadecimais no `grep`?

27

Eu estou usando o seguinte comando para grep intervalo de conjunto de caracteres para o código hexadecimal 0900 (em vez de) para 097F (em vez de). Como posso usar código hexadecimal no lugar de अ e व?

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

Eu recebo a seguinte saída:

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

Eu só quero usar código hexadecimal em vez de अ e व no comando acima.

Se o uso do código hexadecimal não for possível, posso usar o código unicode em vez do código hexadecimal para o conjunto de caracteres ('अ-व')?

Estou usando o Ubuntu 10.04

Dhrubo Bhattacharjee
fonte
11
O que você quer dizer com "não está funcionando"? Também -vinverte a correspondência, pelo texto da sua pergunta parece que não é o que você deseja.
Christian.K
@ Christian.K Desculpe pela demora ... Eu editei a pergunta, por favor dê uma olhada.
Ainda estou esperando por uma resposta apropriada. :(
Dhrubo Bhattacharjee

Respostas:

21

Olhe para esta pergunta .

O texto geralmente é codificado em UTF-8; então você deve usar os valores hexadecimais dos bytes usados ​​na codificação utf-8.

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

e

grep '[अ-व]'

são equivalentes e executam uma correspondência baseada em código de idioma (ou seja, a correspondência depende das regras de classificação do script devanagari (ou seja, a correspondência NÃO é "qualquer caractere entre \ u0905 e \ 0935", mas "qualquer coisa que seja classificada entre devanagari A e devanagari VA "; pode haver diferenças.

Por outro lado, você tem este (nota -P):

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

que fará uma correspondência binária com esses valores de bytes .

Pablo Saratxaga
fonte
2
Por favor, explique o prefixo "["$'e sufixo"]"
Jonathan Komar
6

Se o escape de shell for suficiente, você poderá usar a $'\xHH'sintaxe da seguinte maneira:

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

Isso é suficiente para o seu caso de uso?

Stéphane Gimenez
fonte
echo 'अ-व' | hdme dáe0 a4 85 - e0 a4 b5
enzotib
Na verdade, o OP deu valores Unicode, não hexadecimal despeja na codificação UTF-8: - / Desde grepnão está relacionada com qualquer lib, eu acho que não é possível ter a conversão gama ser realizada por grep: - /
Stéphane Gimenez
11
Btw, zshé capaz de interpretar "\u0900"e "\u097F", mas o comportamento dependerá do intervalo codificado em UTF-8 ser contínuo (provavelmente é).
Stéphane Gimenez
Nenhum grep -v "<[" $ '\ x09 \ x00' "-" $ '\ x09 \ x7F' "] * \ s" fornece a seguinte saída <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> .... Isso não é esperado. :(, posso usar unicode em vez de código hexadecimal ou conjunto de caracteres ( 'अ-व')?
Dhrubo Bhattacharjee
6

O valor "hexadecimal" que 0x0900você escreveu é exatamente o valor do ponto de código UNICODE, que também está em hexadecimal.

código hexadecimal 0900 (em vez de अ)

Eu acredito que o que você quer dizer é o ponto de código Unicode hexadecimal: U0905.

O personagem de U-0900 não é o que você usou: .
Esse caractere é U0905 , parte desta página Unicode ou listado nesta página .

Em bash(instalado por padrão no Ubuntu) ou diretamente com o programa em: /usr/bin/printf(mas não com shprintf), um caractere Unicode pode ser produzido com:

$ printf '\u0905'

$ /usr/bin/printf '\u0905'

No entanto, esse caractere, proveniente de um número de ponto de código, pode ser representado por vários fluxos de bytes, dependendo da página de código usada.
Deveria ser óbvio que \U0905está 0x09 0x05em UTF-16 (UCS-2, etc)
e 0x00 0x00 0x09 0x05em UTF-32.
Pode não ser óbvio, mas no utf-8 é representado por 0xe0 0xa4 0x85:

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

Se a localidade do seu console for algo semelhante a en_US.UTF-8.

E eu estou falando sobre o shell, porque é aquele que transforma uma string no que o aplicativo recebe. Este:

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

faz grep "ver" o personagem que você precisa.
Para entender a linha acima, você pode usar echo:

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

Em seguida, podemos criar um intervalo de caracteres, conforme solicitado:

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

Isso responde sua pergunta:

Como posso usar código hexadecimal no lugar de अ e व?

sorontar
fonte
Essa é de longe a melhor resposta - ela aborda claramente a questão das representações dos pontos unicode no shell e mostra como ir e voltar entre os códigos hexadecimais.
stefano
2

queríamos converter as aspas duplas não-ascii abertas e as aspas duplas em aspas duplas regulares ("). Também as aspas simples não-ascii em aspas simples regulares (').

para vê-los no arquivo (ubuntu bash shell):

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

traduza-os:

$ /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
fonte