正则表达式 "punct" 字符 class 根据 Ruby 版本匹配不同的字符
Regex "punct" character class matches different characters depending on Ruby version
Ruby的字符类为标点字符,即[:punct:]
、\p{Punct}
或\p{P}
似乎匹配不同的字符,具体取决于我使用的 Ruby 版本。
这是一个小例子:(很抱歉弄乱了 SO 的语法高亮显示)
# punct.rb
chars = <<-EOD.split
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~
EOD
matched, not_matched = chars.partition { |c| c =~ /[[:punct:]]/ }
puts " matched: #{matched.join}"
puts "not matched: #{not_matched.join}"
使用 Ruby 1.9.3 并再次使用 Ruby 2.4.0 我得到:
matched: !"#$%&'()*+,-./:;<=>?@[]^_`{|}~
not matched:
但是中间的各种 Ruby 版本 (2.0.x, 2.1.x, 2.2.x, 2.3.x) 给出我:
matched: !"#%&'()*,-./:;?@[]_{}
not matched: $+<=>^`|~
为什么会这样,什么是正确的行为?更重要的是:如何在 Ruby 个版本中获得一致的结果?
尝试更改我的语言环境无济于事(如 Why does Ruby /[[:punct:]]/ miss some punctuation characters? 所建议)。
Ruby 1.9.3 使用 US_ASCII 作为默认编码,正确匹配所有标点符号。 Ruby 2.0 将其默认编码切换为 UTF-8,引入了您发现的错误,导致标点符号匹配不当。 Ruby 2.4 修复了这个错误。
正确的行为是匹配所有标点符号,如 ruby 1.9.3 和 2.4 所做的那样。这与标点符号的 POSIX 正则表达式定义一致。
使您的代码保持一致的一种选择是将所有字符串编码为 US_ASCII 或没有 UTF-8 错误的替代方法:
matched, unmatched = chars.partition { |c| c.encode(Encoding::US_ASCII) =~ /[[:punct:]]/ }
但这可能并不理想,因为它会强制您对字符串使用限制性编码。
另一个选项是手动定义标点符号:
/[!"\#$%&'()*+,\-./:;<=>?@\[\\]^_`{|}~]/
它有点不雅观,但您可以将其放入变量中,然后以这种方式将其添加到正则表达式中:
punctuation = "[!\"\#$%&'()*+,\-./:;<=>?@\[\\]^_`{|}~]"
my_regex = /#{punctuation}/
Ruby的字符类为标点字符,即[:punct:]
、\p{Punct}
或\p{P}
似乎匹配不同的字符,具体取决于我使用的 Ruby 版本。
这是一个小例子:(很抱歉弄乱了 SO 的语法高亮显示)
# punct.rb
chars = <<-EOD.split
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~
EOD
matched, not_matched = chars.partition { |c| c =~ /[[:punct:]]/ }
puts " matched: #{matched.join}"
puts "not matched: #{not_matched.join}"
使用 Ruby 1.9.3 并再次使用 Ruby 2.4.0 我得到:
matched: !"#$%&'()*+,-./:;<=>?@[]^_`{|}~
not matched:
但是中间的各种 Ruby 版本 (2.0.x, 2.1.x, 2.2.x, 2.3.x) 给出我:
matched: !"#%&'()*,-./:;?@[]_{}
not matched: $+<=>^`|~
为什么会这样,什么是正确的行为?更重要的是:如何在 Ruby 个版本中获得一致的结果?
尝试更改我的语言环境无济于事(如 Why does Ruby /[[:punct:]]/ miss some punctuation characters? 所建议)。
Ruby 1.9.3 使用 US_ASCII 作为默认编码,正确匹配所有标点符号。 Ruby 2.0 将其默认编码切换为 UTF-8,引入了您发现的错误,导致标点符号匹配不当。 Ruby 2.4 修复了这个错误。
正确的行为是匹配所有标点符号,如 ruby 1.9.3 和 2.4 所做的那样。这与标点符号的 POSIX 正则表达式定义一致。
使您的代码保持一致的一种选择是将所有字符串编码为 US_ASCII 或没有 UTF-8 错误的替代方法:
matched, unmatched = chars.partition { |c| c.encode(Encoding::US_ASCII) =~ /[[:punct:]]/ }
但这可能并不理想,因为它会强制您对字符串使用限制性编码。
另一个选项是手动定义标点符号:
/[!"\#$%&'()*+,\-./:;<=>?@\[\\]^_`{|}~]/
它有点不雅观,但您可以将其放入变量中,然后以这种方式将其添加到正则表达式中:
punctuation = "[!\"\#$%&'()*+,\-./:;<=>?@\[\\]^_`{|}~]"
my_regex = /#{punctuation}/