maa*_*nus 17 java regex unicode case-insensitive case-folding
这听起来像个笑话,但我可以证明这一点.
假设:
s且仅当它匹配时才匹配s.toUpperCase().以下所有内容都非常符合逻辑并且在Java中保留:
"?".matches(".") LATIN SMALL LIGATURE FFI(U + FB03)是一个字符,因此它必须匹配"ß".matches(".") LATIN SMALL LETTER SHARP S(U + 00DF)是一个字符,因此它必须匹配"?".toUpperCase().equals("FFI") 按Unicode标准(没有资本连字FFI)"ß".toUpperCase().equals("SS") 按照Unicode标准(有一个大写的S,但它没有被使用)"FfI".toUpperCase().equals("FFI") 明显"sS".toUpperCase.equals("SS") 明显因此,假设正则表达式中的第一个点代表?第二个点,则正则ß表达式必须匹配"FFISS",并且因为不区分大小写也是"FfIsS".
我真的希望有一些错误,否则正则表达式会变得非常不可用.
问题:
tch*_*ist 18
答案是否定的,点会不匹配ss不敏感的情况下,虽然原因是稍微深奥.
然而,一些最了解这类事物的人经常提出你的谜题,因为他们也觉得它会导致矛盾.
Unicode中有两种形式的大小写映射.有一个简单的案例映射,其中一个代码点只映射到另一个代码点.所以如果length(s) == 1,那么你也可以保证,Unicode折叠地图length(fc(s)) == 1在哪里fc.但它也适用于uc,tc和lc大小写映射.
问题在于,您没有获得分析某些类型的真实世界文本的好结果,那么您可以制作那些精确的1:1长度保证.
事实上,其中有不少.这些数字表示在四个案例图下,有多少个别BMP代码点映射到指定的长度:
length lc == 2 1
length lc == 3 0
length fc == 2 88
length fc == 3 16
length uc == 2 86
length uc == 3 16
length tc == 2 32
length tc == 3 16
Run Code Online (Sandbox Code Playgroud)
在全外壳,而不是Java的正则表达式使用简单的外壳,你确实可以得到像tschüß和TSCHÜSS匹配,即使它们是不相等的长度.Perl和Ruby在进行不区分大小写的比较时使用完整的大小写映射.如果你不小心,这会在否定的角色类中导致奇怪的悖论.
但这就是问题:不区分大小写的匹配不执行传递操作.换句话说,如果.比赛ß和下不区分大小写的匹配,ß匹配SS,这并不意味着它通过传递.匹配SS不敏感案件.尽管比我更聪明的人已经深入思考过这个问题,但这并不是那样的.
但是,这两个代码点:
做肯定不区分大小写的匹配,不仅对方也SS,Ss,sS,并ss在全案的映射.他们只是在简单的案例映射下不这样做.
Unicode确实对此做出了一些保证.其一是,如果length(s) == n,这length(fn(s)) <= 3*n哪里fn是任何4箱子映射:lc,fc,uc,和tc.
如果您认为这很糟糕,那么当您考虑规范化形式时,它实际上会变得更糟糕.这里的保证是5×而不是3×.所以length(NFx(s)) <= 5 * length(s),正如你所看到的那样变得昂贵.
下面是等效表,显示在四种规范化形式的每一种下,有多少代码点扩展到多个代码点:
length NFC == 2 70
length NFC == 3 2
length NFC == 4 0
length NFC == 5 0
length NFKC == 2 686
length NFKC == 3 404
length NFKC == 4 53
length NFKC == 5 15
length NFD == 2 762
length NFD == 3 220
length NFD == 4 36
length NFD == 5 0
length NFKD == 2 1345
length NFKD == 3 642
length NFKD == 4 109
length NFKD == 5 16
Run Code Online (Sandbox Code Playgroud)
不是很了不起?有一段时间,Unicode希望尝试在模式匹配中构建规范等价.由于上述原因,他们知道它很昂贵,但是由于在一个字形单元内组合字符的必要规范重新排序,它花了一段时间才弄清楚它根本不可能.
出于这个原因,以及许多其他人,如果你想比较"不区分大小写"或"标准化不敏感"的东西,目前的建议是自己通过双方的转换运行它,然后比较结果.
例如,给定一个合适的==代码点代码点等价运算符
fc(a) == fc(b)
Run Code Online (Sandbox Code Playgroud)
类似地,对于=~模式匹配运算符(当然,它以传统方式工作,而不是像Java match那种不恰当地锚定东西的破碎方法):
fc(a) =~ fc(b)
Run Code Online (Sandbox Code Playgroud)
问题在于,您不能再在模式的特定部分打开或关闭不区分大小写,例如
/aaa(?i:xxx)bbb/
Run Code Online (Sandbox Code Playgroud)
并且只有xxx部分不区分大小写.
完整的外壳很难,但它可以(在大多数情况下)完成,就像Perl和Ruby已经证明的那样.但在你应该理解的地方,这也是非直观的(阅读:令人惊讶).你必须用括号中的角色类做特殊的事情,尤其是他们的否定,或者导致废话.
最后,为了使事情真正复杂化,在现实世界中,您必须做的不仅仅是案例映射和规范化中的一个或两个.在某些国家/地区,事情变得更加复杂.例如,在德语电话簿中,带有变音符号的元音与相同的基本元音后跟字母e完全相同.所以,在某些情况下müß会出现与MUESS大小写不相符的情况.
要做到这一切,你真的需要不只是完整的案例映射和规范化表,DUCET本身,默认Unicode整理元素表,甚至CLDR数据(参见参考书目):
#!/usr/bin/perl
use utf8;
use open qw(:utf8 :std);
use Unicode::Collate::Locale;
my $Collator = Unicode::Collate::Locale->new(
locale => "de__phonebook",
level => 1,
normalization => undef,
);
my $full = "Ich müß Perl studieren.";
my $sub = "MUESS";
if (my ($pos,$len) = $Collator->index($full, $sub)) {
my $match = substr($full, $pos, $len);
print "Found match of literal ‹$sub› at position $pos in ‹$full› as ‹$match›\n";
}
Run Code Online (Sandbox Code Playgroud)
如果你运行它,你会发现它确实有效:
在<IchmüßPerlstudieren.中找到第4位文字<MUESS>的匹配作为<müß>
大多数例子是从4-4 个版编程的Perl其作者的一种许可.:)我在那里写了很多关于这种Unicode问题的东西,这些东西并不是Perl特有的,而是整体上对Unicode的一般性.
该单字符,让我喜欢收集这些统计数据(1)程序:
$ unichars 'length fc == 2' | wc -l
88
$ unichars 'length NFKD == 4' | wc -l
109
$ unichars '/ss/i'
U+00DF ? ß LATIN SMALL LETTER SHARP S
U+1E9E ? ? LATIN CAPITAL LETTER SHARP S
Run Code Online (Sandbox Code Playgroud)
是Brian Foy一直非常友好地为我维护的Unicode :: Tussle CPAN模块套件的一部分.
也可以看看:
| 归档时间: |
|
| 查看次数: |
1213 次 |
| 最近记录: |