我在文本文件中有 Unicode 字符 ᚠ,由其 Unicode 代码点 16A0 表示(该文本文件被编码(?)为 utf-8)。
当我这样做时,grep '\u16A0' test.txt
我没有得到任何结果。我如何 grep 该字符?
答案1
答案2
你可以使用乌格勒普作为 grep 的直接替换,以匹配 Unicode 代码点 U+16A0:
ugrep '\x{16A0}' test.txt
它采用与 grep 相同的选项,但提供更多的功能,例如:
ugrep 搜索 UTF-8/16/32 输入和其他格式。选项 -Q 允许搜索许多其他文件格式,例如 ISO-8859-1 到 16、EBCDIC、代码页 437、850、858、1250 到 1258、MacRoman 和 KIO8。
ugrep 匹配 Unicode 模式默认情况下(使用选项 -U 禁用)。正则表达式模式语法符合 POSIX ERE 标准,并使用类似 PCRE 的语法进行了扩展。选项 -P 也可用于 Perl 与 Unicode 模式的匹配。
看GitHub 上的 ugrep了解详情。
答案3
使用乐(以前称为 Perl_6)
输入示例:
https://www.cogsci.ed.ac.uk/~richard/unicode-sample-3-2.html
匹配字符,打印行:
~$ raku -ne '.put if m/ \x[16A0] /;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
#OR:
~$ raku -e 'lines.grep(/ \x[16A0] /).put;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
匹配字符,打印(空格分隔的)“word”:
~$ raku -ne 'for .words() { .put if m/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'words.grep(/ \x[16A0] /).put;' file
ᚠ
匹配字符,打印(精确)匹配:
~$ raku -e 'given slurp() { put m:g/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).put;' file
ᚠ
匹配字符,计算匹配次数并打印:
~$ raku -e 'given slurp() { put m:g/ \x[16A0] /.Int };' file
1
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).elems.put;' file
1
笔记:
在 Raku 中,您可以轻松地匹配 Unicode 名称
\c[RUNIC LETTER FEHU FEOH FE F]
,例如 ,它给出的结果与上面的匹配结果相同\x[16A0]
。在 Raku 中,您可以轻松地匹配 Unicode 字符,例如,其给出的结果与匹配或以上
ᚠ
匹配的结果相同。\x[16A0]
\c[RUNIC LETTER FEHU FEOH FE F]
在 Raku 中,您可以使用 Unicode 变量(以及 Unicode 运算符)。所以这有效:
~$ 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
答案4
使用perl
、pcre2grep
或至少使用或可以使用 PCRE 或 PCRE2 的pcregrep
任何实现,您可以使用来匹配具有值的字符(或仅用于值 <= 0xff)。grep
\x{16A0}
0x16A0
\xe9
为了使该值成为 unicode 代码点,我们需要告诉他们输入必须从 UTF-8 解码。在 PCRE/PCRE2 中,这是通过(*UTF)
在模式的开头使用(主要相当于传递PCRE_UTF
给正则表达式引擎),尽管最新版本的 GNUgrep
至少在使用 UTF-8 作为其字符映射的语言环境中调用时会自动执行此操作。对于pcregrep
和pcre2grep
,也可以使用 选项启用该-u
功能(另请参见-U
)pcre2grep
。
在 中perl
,这是通过环境变量-C
的 (big char) 选项PERL_UNICODE
。单独使用时-C
,缩写是-CSDL
如果语言环境像 GNU 一样使用 UTF-8,则解码/重新编码将输入/输出重新编码为 UTF-8 grep
,或者-CSD
无条件地执行此操作,或者使用模块等从任何编码显式解码Encode
。
在PCRE2(由GNU 或最新版本perl
使用)中,您还可以使用.其 Unicode 名称为: .pcre2grep
grep
\N{U+16A0}
perl
\N{RUNIC LETTER FEHU FEOH FE F}
所以:
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}'
要根据未以 UTF-8 编码的输入上的 Unicode 值匹配字符,这些字符将不起作用,因为它们只能在 UTF-8 中起作用。在单字节字符集中,将按\xHH
值(相应字符集中的代码点,而不是 Unicode 中的代码点)工作。
例如,在en_GB.iso885915
区域设置中,欧元符号 (U+20AC) 位于 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'
€
因此选项是将文本转换为 UTF-8:
$ echo € | iconv -t utf-8 | LC_ALL=C.UTF-8 grep -P '\x{20ac}' | iconv -f utf-8
€
或者,如果使用perl
use-Mopen=locale
而不是-C
告诉它根据语言环境的字符集而不是 UTF-8 对输入/输出进行解码/编码:
$ echo € | perl -Mopen=locale -ne 'print if /\N{U+20ac}/'
€
或者不进行任何解码,但匹配区域设置中该字符的字节值。
例如,使用 GNU 或 zsh 或最新版本的 bash printf
:
$ locale charmap
ISO-8859-15
$ printf '\u20ac' | od -An -vtx1
a4
$ echo € | grep -F -- "$(printf '\u20ac')"
€
在 zsh 中,您还可以使用$'\u20ac'
which 将扩展为当时当前语言环境中字符的编码(如果该语言环境中没有此类字符,则报告错误)。
$ echo € | grep -F -- $'\u20ac'
€
其他几个 shell 也从 zsh 复制了它$'\uHHHH'
,包括 ksh93、bash、mksh 和一些基于 ash 的 shell,但有一些不幸的差异:在 ksh 中,无论语言环境如何,它都会以 UTF-8 进行扩展,而对于 bash,它会在读取代码时的语言环境而不是运行代码时的语言环境,例如,在bash
:
LC_CTYPE=C.UTF-8
{
LC_CTYPE=en_GB.iso885915
printf '\xA4\n' | grep -F -- $'\u20ac'
}
或者:
LC_CTYPE=C.UTF-8
euro() {
grep -F -- $'\u20ac'
}
LC_CTYPE=en_GB.iso885915
printf '\xa4\n' | euro
不起作用,因为在这两种情况下,$'\u20ac'
都会扩展为其 UTF-8 编码,因为在 shell 解析LC_CTYPE=en_GB.iso885915
时尚未运行。$'\u20ac'