使用测试2.txt
$ cat /tmp/test2.txt | hexdump -C
00000000 47 61 6c 6c 6f 20 63 65 6c 74 69 63 6f 0a 47 65 |Gallo celtico.Ge|
00000010 73 97 20 42 61 6d 62 69 6e 6f 0a |s. Bambino.|
以下是发生的事情awk
:
$ cat /tmp/test2.txt | awk '/\x97/{print}'
Ges Bambino
$ cat /tmp/test2.txt | awk '/[\x7F-\xFF]/{next;}; 1'
Gallo celtico
Ges Bambino
即,行Ges Bambino
line 包含一个字符\x97
,并awk
确认了第一个命令中的 。但是,\x97
处于 的范围内\x7F-\xFF
,因此第二个命令中应该跳过该行,但事实并非如此。
在我看来这确实是一个awk
错误。
有什么评论吗?
PS.使其更加明显:
$ cat /tmp/test2.txt | awk '/\x97/{next}; 1'
Gallo celtico
$ cat /tmp/test2.txt | awk '/[\x97]/{next}; 1'
Gallo celtico
Ges Bambino
更新:
正如@KamilMaciorowski 指出的那样,它与本地相关。即上述情况发生在
$ set | egrep '^LANG|^LC'
LANG=zh_CN.UTF-8
而两者
cat /tmp/test2.txt | LC_ALL=C awk '/[\x97]/{next}; 1'
cat /tmp/test2.txt | LC_ALL=C awk '/[\x7F-\xFF]/{next;}; 1'
给出了正确的结果。
但这是一个问题,不是吗?
答案1
C
字节和字符仅在默认(又名)语言环境中相同POSIX
,但在所有其他语言环境中它们都不同。因此,如果您的系统默认使用 UTF-8 语言环境(例如en_US.UTF-8
),则 gawk 正则表达式中括号中的“字符类”基于人物,而不是单个字节。
例如,/[eęė]/
相当于/[e\xC4\x99\xC4\x97]/
假设一个 *.UTF-8 语言环境;但是,它将匹配字母,ę
但不匹配č
,尽管两者都有一个C4
字节。(出于某种原因,这与普通的/\xC4/
外部一个字符类,做匹配文字字节C4
。)
无论如何,这同样适用于字符类内的范围,并且由于字节FF
不能构成有效的 UTF-8 序列,因此正则表达式库可能只是将整个范围声明为无效或其他。
gawk 有一个-b
,--characters-as-bytes
选项可以禁用此功能。