为什么Ruby / [[:punct:]] /会遗漏一些标点字符?

时间:2012-06-21 01:41:01

标签: ruby regex posix

Ruby /[[:punct:]]/应该匹配所有“标点字符”。根据{{​​3}},这意味着每个POSIX标准/[\]\[!"#$%&'()*+,./:;<=>?@\^_`{|}~-]/

匹配:-[]\;',./!@#%&*()_{}::"?

但是,它匹配:=`~$^+|<>(至少在ruby 1.9.3p194中)。

是什么给出了?

2 个答案:

答案 0 :(得分:11)

标点字符类由语言环境定义。开放组LC_TYPE definition for punct说:

  

定义要分类为标点字符的字符。在POSIX语言环境中,既不应包括<space>,也不应包括alpha,digit或cntrl类中的任何字符。在区域设置定义文件中,不会为关键字upper,lower,alpha,digit,cntrl,xdigit或指定的关键字指定字符。

基本上,它定义了如何通过排除其他字符类来定义 punct ,但它实际上并不直接定义标点符号 - 这是语言环境的工作。

我无法找到每个区域设置中的规范参考。也许别人知道。同时,您可以找到与您想要的 punct 字符类匹配的LC_TYPE,或者直接指定该类。

答案 1 :(得分:1)

大于号码位于"Symbol, Math" category,而不是标点符号类别。如果你强制使用正则表达式的编码为UTF-8(默认为源编码,可能你的源是UTF-8编码,而我的默认源是其他的),你可以看到这一点:

2.1.2 :004 > /[[:punct:]]/u =~ '<'
 => nil 
2.1.2 :005 > /[[:punct:]]/ =~ '<'
 => 0 

如果强制使用正则表达式进行ASCII编码(/ n - 更多选项here),您会看到它分类为'&lt;'在punct中,我认为这就是你想要的。但是,如果源包含UTF-8的ASCII子集之外的字符,则可能会出现问题。

2.1.2 :009 > /[[:punct:]]/n =~ '<'
 => 0 

更好的解决方案是在正则表达式中使用“符号”类别而不是“匹配”类别,它匹配“&lt;”采用UTF-8编码:

2.1.2 :012 > /\p{S}/u =~ '<'
 => 0 

有一个较长的类别列表here