Come specificare i caratteri usando i codici esadecimali in `grep`?


27

Sto usando il seguente comando per grep l'intervallo del set di caratteri per il codice esadecimale da 0900 (anziché अ) a 097F (anziché व). Come posso usare il codice esadecimale al posto di अ 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

Ottengo il seguente output:

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

Voglio solo usare il codice esadecimale invece di अ e व nel comando sopra.

Se non è possibile utilizzare il codice esadecimale, posso usare unicode invece del codice esadecimale per il set di caratteri ('अ-व')?

Sto usando Ubuntu 10.04


1
Cosa intendi con "non funzionante"? -vInverte anche la corrispondenza, dal testo della domanda sembra che non sia quello che vuoi.
Christian.K,

@ Christian.K Scusate il ritardo ... Ho modificato la domanda, per favore date un'occhiata.

Sto ancora aspettando una risposta adeguata. :(
Dhrubo Bhattacharjee,

Risposte:


21

Guarda questa domanda .

Il testo è generalmente codificato in UTF-8; quindi devi usare i valori esadecimali dei byte usati nella codifica utf-8.

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

e

grep '[अ-व]'

sono equivalenti e eseguono una corrispondenza basata su locale (ovvero, la corrispondenza dipende dalle regole di ordinamento dello script devanagari (ovvero, la corrispondenza NON è "alcun carattere tra \ u0905 e \ 0935" ma invece "qualsiasi ordinamento tra devanagari A e devanagari VA "; potrebbero esserci delle differenze.

D'altra parte, hai questo (nota -P):

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

che farà una corrispondenza binaria con quei valori di byte .


2
Spiega il prefisso "["$'e il suffisso"]"
Jonathan Komar il

6

Se l'escape della shell è sufficiente è possibile utilizzare la $'\xHH'sintassi in questo modo:

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

È abbastanza per il tuo caso d'uso?


echo 'अ-व' | hdmi dàe0 a4 85 - e0 a4 b5
enzotib il

In effetti l'OP ha fornito valori unicode, non dump esadecimali nella codifica UTF-8: - / Dato che grepnon è collegato con alcuna lib, suppongo che non sia possibile far eseguire la conversione dell'intervallo da grep: - /
Stéphane Gimenez

1
A proposito, zshè in grado di interpretare "\u0900"e "\u097F", ma il comportamento dipenderà dal fatto che l'intervallo codificato UTF-8 è continuo (probabilmente lo è).
Stéphane Gimenez,

Nessun grep -v "<[" $ '\ x09 \ x00' "-" $ '\ x09 \ x7F' "] * \ s" fornisce il seguente output <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> .... Questo non è previsto. :(, Posso usare unicode invece di codice esadecimale o set di caratteri ('अ-व')?
Dhrubo Bhattacharjee,

6

Il valore "esadecimale" che 0x0900hai scritto è esattamente il valore del punto di codice UNICODE che è anche in esadecimale.

codice esadecimale 0900 (anziché अ)

Credo che ciò che si intende dire è il punto di codice Unicode esadecimale: U0905.

Il carattere a U-0900 non è quello utilizzato: .
Quel personaggio è U0905 , parte di questa pagina Unicode , o elencato in questa pagina .

In bash(installato di default in Ubuntu), o direttamente con il programma su: /usr/bin/printf(ma non con shprintf), un carattere Unicode può essere prodotto con:

$ printf '\u0905'

$ /usr/bin/printf '\u0905'

Tuttavia, quel carattere, che proviene da un numero di punto di codice, potrebbe essere rappresentato da diversi flussi di byte a seconda della tabella codici utilizzata.
Dovrebbe essere ovvio che si \U0905trova 0x09 0x05in UTF-16 (UCS-2, ecc.)
E 0x00 0x00 0x09 0x05in UTF-32.
Potrebbe non essere ovvio, ma in utf-8 è rappresentato da 0xe0 0xa4 0x85:

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

Se le impostazioni internazionali della tua console sono simili a en_US.UTF-8.

E sto parlando della shell perché è quella che trasforma una stringa in ciò che l'applicazione riceve. Questo:

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

fa in modo che grep "veda" il personaggio di cui hai bisogno.
Per comprendere la riga sopra puoi usare l'eco:

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

Quindi, possiamo creare un intervallo di caratteri, come da lei richiesto:

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

Che rispondono alla tua domanda:

Come posso usare il codice esadecimale al posto di अ e व?


Questa è di gran lunga la risposta migliore --- affronta chiaramente il problema delle rappresentazioni dei punti unicode nella shell e mostra come andare avanti e indietro tra loro i codici esadecimali.
Stefano

2

volevamo convertire la doppia virgoletta aperta non ascii e chiudere la virgoletta doppia in virgolette doppie regolari ("). Anche la virgoletta singola non ascii in virgoletta singola regolare (').

per vederli nel file (ubuntu bash shell):

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

traducili:

$ /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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.