Tengo el carácter Unicode ᚠ, representado por su punto de código Unicode 16A0, en un archivo de texto (el archivo de texto está codificado (?) como utf-8).
Cuando lo hago grep '\u16A0' test.txt
no obtengo ningún resultado. ¿Cómo puedo agarrar ese personaje?
Respuesta1
Puedes usarcotización ANSI-Cproporcionado por su shell, para reemplazar los caracteres de escape con barra invertida según lo especificado por el estándar ANSI C. Esto debería funcionar para cualquier comando, no solo grep
, en shells como Bash y Zsh:
grep $'\u16A0'
Para ver algunos ejemplos más complejos, puede consultaresta pregunta relacionaday sus respuestas.
Respuesta2
Podrías usarugrepcomo reemplazo directo de grep para que coincida con el punto de código Unicode U+16A0:
ugrep '\x{16A0}' test.txt
Toma las mismas opciones que grep pero ofrece muchas más funciones, como:
ugrep busca entradas UTF-8/16/32 y otros formatos. La opción -Q permite buscar muchos otros formatos de archivos, como ISO-8859-1 a 16, EBCDIC, páginas de códigos 437, 850, 858, 1250 a 1258, MacRoman y KIO8.
ugrep coincide con patrones Unicodede forma predeterminada (deshabilitado con la opción -U). La sintaxis del patrón de expresión regular es compatible con POSIX ERE ampliada con una sintaxis similar a PCRE. La opción -P también se puede utilizar para hacer coincidir Perl con patrones Unicode.
Verugrep en GitHubpara detalles.
Respuesta3
Usandorakú(anteriormente conocido como Perl_6)
Entrada de muestra:
https://www.cogsci.ed.ac.uk/~richard/unicode-sample-3-2.html
Haga coincidir el carácter, imprima la línea:
~$ raku -ne '.put if m/ \x[16A0] /;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
#OR:
~$ raku -e 'lines.grep(/ \x[16A0] /).put;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
Haga coincidir el carácter, imprima la "palabra" (separada por espacios en blanco):
~$ raku -ne 'for .words() { .put if m/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'words.grep(/ \x[16A0] /).put;' file
ᚠ
Haga coincidir el carácter, imprima las coincidencias (exactas):
~$ raku -e 'given slurp() { put m:g/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).put;' file
ᚠ
Haga coincidir el personaje, cuente las coincidencias e imprima:
~$ raku -e 'given slurp() { put m:g/ \x[16A0] /.Int };' file
1
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).elems.put;' file
1
NOTAS:
En Raku puedes comparar fácilmente con un nombre Unicode como
\c[RUNIC LETTER FEHU FEOH FE F]
, lo que da los mismos resultados que la comparación\x[16A0]
anterior.En Raku puedes comparar fácilmente con un carácter Unicode como
ᚠ
, lo que da los mismos resultados que comparar con\x[16A0]
o\c[RUNIC LETTER FEHU FEOH FE F]
superior.En Raku, puedes usar variables Unicode (así como operadores Unicode). Entonces esto funciona:
~$ raku -e 'my $ᚠ = slurp.match(/ \x[16A0] /); say $ᚠ.Str.raku;' file
"ᚠ"
https://docs.raku.org/language/regexes#Unicode_properties
https://docs.raku.org/language/unicode
https://docs.raku.org
https://raku.org
Respuesta4
Con perl
, pcre2grep
o pcregrep
cualquier grep
implementación que use o pueda usar PCRE o PCRE2 al menos, puede usarlo \x{16A0}
para hacer coincidir el carácter con valor 0x16A0
(o solo \xe9
para valores <= 0xff).
Para que ese valor sea el punto de código Unicode, debemos decirles que la entrada debe decodificarse en UTF-8. En PCRE/PCRE2, eso es usando (*UTF)
al inicio del patrón (principalmente equivalente a pasar PCRE_UTF
al motor de expresiones regulares), aunque las versiones recientes de GNU grep
al menos lo hacen automáticamente cuando se invoca en una configuración regional que usa UTF-8 como su mapa de encanto. Con pcregrep
y pcre2grep
, eso también se puede habilitar con la -u
opción (ver también -U
en pcre2grep
).
En perl
, eso es a través de la -C
opción (gran carácter) de la PERL_UNICODE
variable de entorno. Donde -C
solo, abreviatura -CSDL
es decodificar/recodificar recodificar entrada/salida como UTF-8 si la configuración regional usa UTF-8 como grep
lo hace GNU, o -CSD
hacerlo incondicionalmente, o decodificar explícitamente desde cualquier codificación usando, por ejemplo, el Encode
módulo.
En perl
y PCRE2 (como se usa en pcre2grep
las versiones recientes de GNU grep
), también puedes usar \N{U+16A0}
. Y en perl
su nombre Unicode: \N{RUNIC LETTER FEHU FEOH FE F}
.
Entonces:
perl -C -ne 'print if /\x{16A0}/'
perl -C -ne 'print if /\N{U+16A0}/'
perl -C -ne 'print if /\N{RUNIC LETTER FEHU FEOH FE F}/'
PERL_UNICODE=SD perl -ne 'print if /\x{16A0}/'
pcregrep -u '\x{16A0}'
pcregrep '(*UTF)\x{16A0}'
pcre2grep -u '\x{16A0}'
pcre2grep '(*UTF)\x{16A0}'
pcre2grep -U '\x{16A0}'
pcre2grep -u '\N{U+16A0}'
grep -P '\x{16A0}'
Para hacer coincidir un carácter según su valor Unicode en una entrada que no está codificada en UTF-8, no funcionará porque solo funciona en UTF-8. En conjuntos de caracteres de un solo byte, \xHH
funcionará con el valor por (el punto de código en el conjunto de caracteres correspondiente, no en Unicode).
Por ejemplo, en la en_GB.iso885915
configuración regional, donde el signo del euro (U+20AC) está en 0xA4.
$ LC_ALL=en_GB.iso885915 luit
$ locale charmap
ISO-8859-15
$ printf %s € | od -An -vtx1
a4
$ echo € | grep -P '\x{20ac}'
grep: character code point value in \x{} or \o{} is too large
$ echo € | grep -P '\N{U+20ac}'
grep: \N{U+dddd} is supported only in Unicode (UTF) mode
$ echo € | grep -P '(*UTF)\N{U+20ac}'
$ echo € | grep -P '\xA4'
€
Entonces las opciones serían convertir el texto a UTF-8:
$ echo € | iconv -t utf-8 | LC_ALL=C.UTF-8 grep -P '\x{20ac}' | iconv -f utf-8
€
O si usa perl
use -Mopen=locale
en lugar de -C
decirle que decodifique/codifique la entrada/salida según el conjunto de caracteres de la configuración regional en lugar de UTF-8:
$ echo € | perl -Mopen=locale -ne 'print if /\N{U+20ac}/'
€
O no realizar ninguna decodificación, pero hacer coincidir el valor de byte de ese carácter en la configuración regional.
Por ejemplo, con GNU o zsh o versiones recientes de bash printf
:
$ locale charmap
ISO-8859-15
$ printf '\u20ac' | od -An -vtx1
a4
$ echo € | grep -F -- "$(printf '\u20ac')"
€
En zsh, también puede usar $'\u20ac'
which se expandirá a la codificación del carácter en la configuración regional actual en ese momento (e informará un error si no existe dicho carácter en esa configuración regional).
$ echo € | grep -F -- $'\u20ac'
€
Varios otros shells han copiado eso $'\uHHHH'
de zsh desde que incluyeron ksh93, bash, mksh y algunos shells basados en ash, pero con algunas diferencias desafortunadas: en ksh, se expandió en UTF-8 independientemente de la configuración regional, y con bash, se expandió en el configuración regional en el momento en que se lee el código en lugar de en el momento en que se ejecuta el código, por ejemplo, en bash
:
LC_CTYPE=C.UTF-8
{
LC_CTYPE=en_GB.iso885915
printf '\xA4\n' | grep -F -- $'\u20ac'
}
O:
LC_CTYPE=C.UTF-8
euro() {
grep -F -- $'\u20ac'
}
LC_CTYPE=en_GB.iso885915
printf '\xa4\n' | euro
No funcionará porque en ambos casos, $'\u20ac'
se expande a su codificación UTF-8 ya que LC_CTYPE=en_GB.iso885915
no se había ejecutado cuando $'\u20ac'
el shell lo analizó.