如何 grep 查找一系列 unicode 字符?

如何 grep 查找一系列 unicode 字符?

如何 grep 查找一系列 unicode 字符?

我见过一个角色的例子。如何用 unicode 值来 grep 字符?

我对 shell 替换方法以外的方法感兴趣

因为 shell 替换似乎有点有限,例如它似乎不适用于非图形 unicode 字符,例如 \u80 的代码点。

我可以让该方法在一定范围内工作,但仅限于一定程度,因为它不会覆盖像 \u80 (unicode codepoint 80) 这样的非图形字符

$ echo grep [$'\u41'-$'\u45']
grep [A-E]

$ echo 4142434445|xxd -r -p
ABCDE

$ echo 4142434445|xxd -r -p | grep [$'\u41'-$'\u45']
ABCDE

$ 方法在 shell 级别使用替换,因此无法工作,例如从\u0080-\uFFFF\u0080向上查找字符,因为如果 shell 无法显示字符,则它将无法工作。

ugrep 可通过 debian 的 apt-get 获得,但不适用于我在 VPS 上的 ubuntu 版本。我还得再测试一下。

笔记 事实证明,shell 替换方法确实适用于控制字符,因此甚至适用于一系列控制字符或任何 unicode 字符,毫无疑问, ugrep 也适用。最初,当我尝试使用 grep 进行 shell 替换时,我不知不觉地输入了错误的字节。例如echo 418042| xxd -r -p显示,A▒B所以我认为这很好用,我正在尝试 grep 。所以我将错误的数据传递给 grep 。 80 不是 \u80 的 utf-8。高位字符的回显(例如 £)清楚地表明它正在输出 utf-8。echo £ | xxd -p显示c2a30a£ 的 c2a3 是 utf-8。当我输入正确的字节时,它可以工作,例如c280\u80 甚至 echo $'\u80'可以工作。此页面适合显示 utf-8 到 unicode 代码点的映射。https://www.utf8-chartable.de/

虽然 shell 替换确实有效,但我很高兴我有一个答案,它可以执行 shell 替换之外的方法,因为有一个替代方案是好的。

答案1

在 gnu-grep 和类似中,您可以使用 PCRE 选项-P并使用 \x{HHHH}语法

$ grep -o -P '[\x{0410}-\x{042F}]+' # same as: grep -o -P '[А-Я]+'
абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕ

=> АБВГДЕ

答案2

在 GNU 系统上设置LC_COLLATEC至少应保证顺序基于字符映射为多字节的语言环境中的 Unicode 代码点(例如 UTF-8、GB18030),以及其他方式的字节值(在使用 ASCII 或 ISO 的语言环境中) -8859-1 还应该匹配 unicode 代码点顺序)。

所以:

LC_COLLATE=C grep $'[\u1111-\uaaaa]'

应该找到至少包含一个字符的行,其 unicode 代码点介于 U+1111 和 U+AAAA 之间(根据设置指示的区域设置的字符映射进行编码LC_CTYPE)。假设$LC_ALL没有另外设置(因为它优先于$LC_COLLATE)。

我建议避免跨越无效的 U+D800 - U+DFFF 范围。该范围内的代码点保留用于 UTF-16 编码,不适用于有效字符,并且已被某些工具用于对无效字符进行编码。使用 U+0001 和 U+D7FF 以及 U+E000 和 U+10FFFF 内的字符。

您还需要确保范围的边界与您所在区域中的有效字符相对应。的行为$'\uxxxx'(其中 U+xxxx 不是区域设置字符集中的字符)在支持该$'\u...'运算符的 shell 之间有所不同。在某些 shell 中(包括来自 zsh 的 ksh93 $'...'$'\u...'$'\u...'仅适用于使用 UTF-8 作为字符映射的语言环境(请参阅 的输出locale charmap)。

答案3

我采访了一些 Perl 专家。并获得了与 grep 等价的 perl oneliner 来查找一系列 unicode 字符。

$ echo £
£

所以就有了序数的概念,它是字符的数字表示。 (我想无论某物是编码还是代码点。序数这个词对于描述 \x 之后的内容很有用,根据选项,可以是编码,因此存储字节,或者可以是 unicode 代码点,字节但未编码用于存储/写入内存)

它以字节/八位位组为单位。可以用各种基地来表示。

%v是 printf 的格式说明符,

$ perl -e 'printf "%vx\n",A'
41

$ perl -e 'printf "%vx\n",4'
34

%vd 将为 52(字符“4”的十进制数字表示。%vx 是十六进制表示

£ 的 UTF-8 编码为 c2a3 https://www.utf8-chartable.de/

$ echo £ | xxd -p
c2a30a

当使用超过两位数的 \x 时,必须使用花括号。 \X{..}

$ echo £ | perl -CIO -ne 'print if /[\x0A]/'
£

$ echo £ | perl -CIO -ne 'print if /[\x{0080}-\x{FFFF}]/'
£

-CIO 将序数从 UTF-8 表示形式 (c2a3) 转换为 unicode 代码点表示形式 (a3)。因此,当将 -CIO 与 \x 一起使用时,\x 后面的内容应该是 unicode 代码点表示

下面的内容可以将其与 \u0080 及以上的任何内容相匹配。不停止于\uFFFF。只是一个正则表达式的东西。

$ echo £ | perl -CIO -ne 'print if /[^\x00-\x7f]/'
£

如果删除 -CIO 那么您将匹配 UTF-8 字节,而不是 unicode 代码点字节。因为如果没有 -CI,它就不会将 UTF-8 编码字节转换/解释/解码为 un​​icode 代码点。

$ echo £ | perl -ne 'print if /\xc2/'
£

$ echo £ | perl -ne 'print if /\xa3/'
£

所以总结一下

$ echo £ | perl -CIO -ne 'print if /[\x{0080}-\x{FFFF}]/'
£

$ echo £ | perl -CIO -ne 'print if /[^\x00-\x7f]/'
£

$ echo £ | perl -CIO -ne 'print if /[^\x{00}-\{x7f}]/'
£

$ echo £ | perl -CIO -ne 'print if /[^\x{0000}-\{x007f}]/'
£

记录perl -CIOperldoc perlrun

 -C [*number/list*]
         The -C flag controls some of the Perl Unicode features.

...
             I     1   STDIN is assumed to be in UTF-8
             O     2   STDOUT will be in UTF-8

和 perldoc perlunicode 和 perldoc perlre 提到 \x{...}

相关内容