我已经尝试了几个小时来创建一个概念上简单的过滤器,我可以在命令行上使用,但没有成功。任务是过滤掉包含Hangul Jamo字符的所有行,同时保留所有其他行(可能包含ASCII,Hangul Syllable块中的字符等)。
例如,如果输入是
foo
ᅤᆨ
간
输出将包含第一行和第三行,但不包含第二行,因为第二行包含Jamo字符。 (以上并不是真正的韩语,只是一个简单的测试用例。)
我对Gnu grep实用程序(版本2.20)非常失望。我会想到ff。会工作:
grep -Pv '[\x{1100}-\x{11FF}]'
但我收到错误消息grep: character value in \x{...} sequence is too large
。 (\ u1100语法,实际的Perl语法,根本不受支持。)
(我注意到我们的版本2.20已经相当老了。如果有人尝试使用更新版本的grep进行上述操作,并且它有效,我肯定会认为这是一个答案 - 我会让我们的IT人员来升级!)
我尝试了sed,但没有进一步。 (对不起,我不记得我尝试过哪些sed命令,但是sed对Unicode块的支持似乎没有比grep更好。)
最后,我尝试了perl(v5.16.3):
perl -ne 'print unless /[\u1100-\u11ff]/'
这至少成功地消除了Jamo线,同时保留了Hangul Syllable线,但它也消除了ASCII线,我不想这样做。我也会想到其中一个ff。会工作:
perl -ne 'print unless /\p{InHangul_Jamo}/'
perl -ne 'print unless /\p{Block: Hangul_Jamo}/'
但似乎都没有任何效果。 (Afaik,我不应该在.*
的每一边都有\p{...}
,但我也试过了;没有运气。)
区域设置:如果重要,我有LANG=en_US.UTF-8
。
我确信我可以用Python做到这一点,但我想理解为什么grep和perl似乎都不起作用,因为它们会更简单。 (如果我对Gnu实用程序的Unicode支持很差,那么为什么......以及什么时候它将被修复。它不像Unicode是新的!)当然我意识到问题可能是我不是当我尝试时,我的嘴巴正确,但如果是这样,grep至少可以获得更好的Unicode使用文档。现在,grep -P
的文档说“这是高度实验性的,grep -P可能会警告未实现的功能。”它似乎一直都是这样。
答案 0 :(得分:2)
解码输入,编码输出。如果有问题的编码是UTF-8,命令行开关-CSD
将会有用。
perl -CSD -ne'print if !/\p{Block: Hangul_Jamo}/'
perl -CSD -ne'print if !/\p{Block: Jamo}/'
perl -CSD -ne'print if !/\p{Blk=Jamo}/'
perl -CSD -ne'print if !/\p{InJamo}/'
perl -CSD -ne'print if !/[\N{U+1100}-\N{U+11FF}]/'
perl -CSD -ne'print if !/[\x{1100}-\x{11FF}]/'
grep -vP '[\x{1100}-\x{11FF}]'
您可能希望添加Hangul_Jamo_Extended_A
,Hangul_Jamo_Extended_B
和Hangul_Compatibility_Jamo
块。
perl -CSD -ne'print if !/[\p{Block: Hangul_Jamo}\p{Block: Hangul_Jamo_Extended_A}\p{Block: Hangul_Jamo_Extended_B}\p{Block: Hangul_Compatibility_Jamo}]/'
perl -CSD -ne'print if !/[\p{Block: Jamo}\p{Block: JamoExtA}\p{Block: JamoExtB}\p{Block: CompatJamo}]/'
perl -CSD -ne'print if !/[\p{Blk=Jamo}\p{Blk=JamoExtA}\p{Blk=JamoExtB}\p{Blk=CompatJamo}]/'
perl -CSD -ne'print if !/[\p{InJamo}\p{InJamoExtA}\p{InJamoExtB}\p{InCompatJamo}]/'
perl -CSD -ne'print if !/[\N{U+1100}-\N{U+11FF}\N{U+A960}-\N{U+A97F}\N{U+D7B0}-\N{U+D7FF}\N{U+3130}-\N{U+318F}]/'
perl -CSD -ne'print if !/[\x{1100}-\x{11FF}\x{A960}-\x{A97F}\x{D7B0}-\x{D7FF}\x{3130}-\x{318F}]/'
grep -vP '[\x{1100}-\x{11FF}\x{A960}-\x{A97F}\x{D7B0}-\x{D7FF}\x{3130}-\x{318F}]'
让我们看看你失败的尝试。
grep -Pv '[\x{1100}-\x{11FF}]'
实际上,这个应该有效,而且对我有用。
$ perl -CSD -e'print "abc\nd\x{1100}f\nghi\n"' | od -t x1
0000000 61 62 63 0a 64 e1 84 80 66 0a 67 68 69 0a
0000016
$ perl -CSD -e'print "abc\nd\x{1100}f\nghi\n"' | grep -Pv '[\x{1100}-\x{11FF}]'
abc
ghi
$ grep --version | head -1
grep (GNU grep) 2.16
我确实在使用grep (GNU grep) 2.10
的旧计算机上收到了您的错误。
perl -ne'print unless /\p{Block: Hangul_Jamo}/'
你没有从/\p{Block: Hangul_Jamo}/
获得任何匹配,因为你匹配编码文本(UTF-8字节,00..FF范围内的字符)而不是解码文本(Unicode代码点,字符)在00000..10FFFF范围内。
perl -ne 'print unless /\p{InHangul_Jamo}/'
\p{Block: X}
,\p{Blk=X}
和\p{InX}
相同。
perl -ne'print unless /[\x{1100}-\x{11FF}]/'
[\x{1100}-\x{11FF}]
相当于\p{Block: Hangul_Jamo}
。
perl -ne'print unless /[\u1100-\u11ff]/'
自从\u
以来,双引号字符串文字中的匹配太多,而正则表达式模式文字则引发了下一个字符。 (例如"\uxyx"
相当于"Xyz"
。)
因此,[\u1100-\u11ff]
相当于[01f]
。