有了这个正则表达式:
regex1 = /\z/
以下字符串匹配:
"hello" =~ regex1 # => 5
"こんにちは" =~ regex1 # => 5
但与这些正则表达式:
regex2 = /#$/?\z/
regex3 = /\n?\z/
他们表现出的差异:
"hello" =~ regex2 # => 5
"hello" =~ regex3 # => 5
"こんにちは" =~ regex2 # => nil
"こんにちは" =~ regex3 # => nil
什么是干扰? 串编码为UTF-8,和OS是Linux的(即, $/
是"\n"
)。 是多字节字符与干扰$/
? 怎么样?
您报告的问题绝对是一个错误Regexp
的RUBY_VERSION #=> "2.0.0"
,但在以前的1.9已经存在,当编码允许多字节字符如__ENCODING__ #=> #<Encoding:UTF-8>
不依赖于Linux上,这是不可能性重现OSX和Windows相同behavoir了。
在同时错误8210将是固定的,我们可以通过隔离和理解在发生问题的情况下帮助。 这也可能是因为当适用于特定案件的任何解决方法是有用的。
我明白,当出现问题:
- 搜索字符串结束前的东西
\z
。 - 和字符串的最后一个字符是多字节 。
- 和搜索之前,将使用零或一个模式
?
- 但零个或一个字符的搜索数量在不到最后一个字符的字节数。
该缺陷可以通过字节数和实际上由正则表达式引擎检查字符的数目之间的误解引起。
有几个例子可以帮助:
测试1:其中最后一个字符:“は”是3个字节:
s = "んにちは"
测试零或字符串的结束之前ん[3个字节]中的一种:
s =~ /ん?\z/u #=> 4" # OK it works 3 == 3
当我们试图用C [2个字节]
s =~ /ç?\z/u #=> nil # KO: BUG when 3 > 2
s =~ /x?ç?\z/u #=> 4 # OK it works 3 == ( 1+2 )
当测试零或\的一个n [1个字节]
s =~ /\n?\z/u #=> nil" # KO: BUG when 3 > 1
s =~ /\n?\n?\z/u #=> nil" # KO: BUG when 3 > 2
s =~ /\n?\n?\n?\z/u #=> 4" # OK it works 3 == ( 1+1+1)
通过TEST1的结果我们可以断言: 如果字符串的最后一个多字节字符是3个字节,那么“零个或一个前”测试时,我们的测试前至少3个字节(不是3个字符)才有效。
测试2:当最后一个字符“C”为2个字节
s = "in French there is the ç"
检查零或ん之一[3字节]”
s =~ /ん?\z/u #=> 24 # OK 2 <= 3
检查零或é之一[2个字节]
s =~ /é?\z/u #=> 24 # OK 2 == 2
s =~ /x?é?\z/u #=> 24 # OK 2 < (2+1)
测试零或\的一个n [1个字节]
s =~ /\n?\z/u #=> nil # KO 2 > 1 ( the BUG occurs )
s =~ /\n?\n?\z/u #=> 24 # OK 2 == (1+1)
s =~ /\n?\n?\n?\z/u #=> 24 # OK 2 < (1+1+1)
通过测试2的结果我们可以断言: 如果字符串的最后一个多字节字符为2个字节,那么“零个或一个前”测试时,我们检查前至少2个字节(而不是2个字符)才有效。
当多字节字符是不是在字符串的结尾,我发现它工作正常。
公共要点我可以在这里测试代码
在Ruby的主干 ,这个问题现在已经被接受为一个错误。 我们希望,这将是固定的。
更新:两个补丁已经张贴在Ruby的主干。