Eu tenho o caractere Unicode ᚠ, representado por seu ponto de código Unicode 16A0, em um arquivo de texto (o arquivo de texto é codificado (?) como utf-8).
Quando faço isso grep '\u16A0' test.txt
não obtenho resultado. Como faço para grep esse personagem?
Responder1
Você pode usarCitação ANSI-Cfornecido pelo seu shell, para substituir caracteres de escape de barra invertida, conforme especificado pelo padrão ANSI C. Isso deve funcionar para qualquer comando, não apenas grep
, em shells como Bash e Zsh:
grep $'\u16A0'
Para alguns exemplos mais complexos, você pode consultaresta questão relacionadae suas respostas.
Responder2
Você poderia usarugrepcomo um substituto imediato do grep para corresponder ao ponto de código Unicode U+16A0:
ugrep '\x{16A0}' test.txt
São necessárias as mesmas opções do grep, mas oferece muito mais recursos, como:
ugrep pesquisa entrada UTF-8/16/32 e outros formatos. A opção -Q permite pesquisar muitos outros formatos de arquivo, como ISO-8859-1 a 16, EBCDIC, páginas de código 437, 850, 858, 1250 a 1258, MacRoman e KIO8.
ugrep corresponde aos padrões Unicodepor padrão (desativado com a opção -U). A sintaxe do padrão de expressão regular é compatível com POSIX ERE estendida com sintaxe semelhante a PCRE. A opção -P também pode ser usada para correspondência Perl com padrões Unicode.
Verugrep no GitHubpara detalhes.
Responder3
UsandoRaku(anteriormente conhecido como Perl_6)
Entrada de amostra:
https://www.cogsci.ed.ac.uk/~richard/unicode-sample-3-2.html
Combine o caractere, imprima a linha:
~$ raku -ne '.put if m/ \x[16A0] /;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
#OR:
~$ raku -e 'lines.grep(/ \x[16A0] /).put;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
Combine o caractere, imprima a "palavra" (separada por espaços em branco):
~$ raku -ne 'for .words() { .put if m/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'words.grep(/ \x[16A0] /).put;' file
ᚠ
Combine o caractere, imprima as correspondências (exatas):
~$ raku -e 'given slurp() { put m:g/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).put;' file
ᚠ
Combine o personagem, conte as correspondências 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:
No Raku, você pode facilmente corresponder a um nome Unicode como
\c[RUNIC LETTER FEHU FEOH FE F]
, que fornece os mesmos resultados da correspondência\x[16A0]
acima.No Raku, você pode facilmente combinar com um caractere Unicode como
ᚠ
, o que fornece os mesmos resultados que a correspondência com\x[16A0]
ou\c[RUNIC LETTER FEHU FEOH FE F]
superior.No Raku, você pode usar variáveis Unicode (bem como operadores Unicode). Então isso funciona:
~$ raku -e 'my $ᚠ = slurp.match(/ \x[16A0] /); say $ᚠ.Str.raku;' file
"ᚠ"
https://docs.raku.org/linguagem/regexes#Unicode_properties
https://docs.raku.org/linguagem/unicode
https://docs.raku.org
https://raku.org
Responder4
Com perl
, pcre2grep
, pcregrep
ou qualquer grep
implementação que use ou possa usar PCRE ou PCRE2 pelo menos, você pode usar \x{16A0}
para combinar o caractere com valor 0x16A0
(ou apenas \xe9
para valores <= 0xff).
Para que esse valor seja o ponto de código Unicode, precisamos dizer a eles que a entrada deve ser decodificada em UTF-8. No PCRE/PCRE2, isso é usado (*UTF)
no início do padrão (principalmente equivalente à passagem PCRE_UTF
para o mecanismo regexp), embora versões recentes do GNU grep
pelo menos façam isso automaticamente quando invocado em um local que usa UTF-8 como seu charmap. Com pcregrep
e pcre2grep
, isso também pode ser habilitado com a -u
opção (ver também -U
em pcre2grep
).
Em perl
, isso é feito através da -C
opção (big char) da PERL_UNICODE
variável de ambiente. Onde -C
sozinho, a abreviação de -CSDL
é decodificar/recodificar, recodificar entrada/saída como UTF-8 se o código do idioma usar UTF-8 como o GNU grep
faz, ou -CSD
fazer isso incondicionalmente, ou decodificar explicitamente de qualquer codificação usando, por exemplo, o Encode
módulo.
No perl
PCRE2 (usado por pcre2grep
versões recentes do GNU grep
), você também pode usar \N{U+16A0}
. E em perl
seu nome Unicode: \N{RUNIC LETTER FEHU FEOH FE F}
.
Então:
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 corresponder um caractere com base em seu valor Unicode em uma entrada que não está codificada em UTF-8, eles não funcionarão, pois funcionam apenas em UTF-8. Em conjuntos de caracteres de byte único, \xHH
funcionará no valor by (o ponto de código no conjunto de caracteres correspondente, não em Unicode).
Por exemplo, na en_GB.iso885915
localidade, onde o sinal do Euro (U+20AC) está em 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'
€
Então as opções seriam converter o texto para UTF-8:
$ echo € | iconv -t utf-8 | LC_ALL=C.UTF-8 grep -P '\x{20ac}' | iconv -f utf-8
€
Ou se estiver usando perl
use -Mopen=locale
em vez de -C
dizer para decodificar/codificar a entrada/saída de acordo com o conjunto de caracteres do código do idioma, em vez de UTF-8:
$ echo € | perl -Mopen=locale -ne 'print if /\N{U+20ac}/'
€
Ou não faça nenhuma decodificação, mas corresponda ao valor do byte desse caractere na localidade.
Por exemplo, com GNU ou zsh ou versões recentes do bash printf
:
$ locale charmap
ISO-8859-15
$ printf '\u20ac' | od -An -vtx1
a4
$ echo € | grep -F -- "$(printf '\u20ac')"
€
No zsh, você também pode usar $'\u20ac'
which irá expandir para a codificação do caractere na localidade atual no momento (e relatar um erro se não houver tal caractere nessa localidade).
$ echo € | grep -F -- $'\u20ac'
€
Vários outros shells copiaram isso $'\uHHHH'
do zsh desde a inclusão do ksh93, bash, mksh e alguns shells baseados em ash, mas com algumas diferenças infelizes: no ksh, isso é expandido em UTF-8, independentemente do local, e com o bash, isso é expandido no locale no momento em que o código é lido, em oposição ao momento em que o código é executado, por exemplo, em bash
:
LC_CTYPE=C.UTF-8
{
LC_CTYPE=en_GB.iso885915
printf '\xA4\n' | grep -F -- $'\u20ac'
}
Ou:
LC_CTYPE=C.UTF-8
euro() {
grep -F -- $'\u20ac'
}
LC_CTYPE=en_GB.iso885915
printf '\xa4\n' | euro
Não funcionará porque, em ambos os casos, o $'\u20ac'
é expandido para sua codificação UTF-8, pois LC_CTYPE=en_GB.iso885915
não foi executado no momento em que $'\u20ac'
foi analisado pelo shell.