给出这样的字符串:
a = 'Somewhere +in+ La-Mancha, in a |place| whose {name} I [do not care] to remember'
我想删除任何非单词和非空格字符。以下代码段按预期工作:
a.gsub(/[^\w\s]/,'')
# => "Somewhere in LaMancha in a place whose name I do not care to remember"
但以下情况不起作用。
a.gsub(/[\W\S]/,'')
# => ""
理论上,两个正则表达式都是等价的,但它们不会以相同的方式工作。有谁知道原因?
是否可以组合负字符类?
答案 0 :(得分:3)
理论上,两个正则表达式都是等价的
完全没有。
这是学校基本的逻辑。
not (A or B)
(或等效地,(not A) and (not B)
)(not A) or (not B)
是不同的。特别地,
[^\w\s]
是:not(单词字符或空格字符)。[\W\S]
是:非单词字符或非空格字符。他们是不同的。例如,非字的字符和空格匹配第二个正则表达式,但不匹配第一个正则字符。
是否可以组合负字符类?
是。字符类有交集运算符&&
。
/[\W&&\S]/
相当于[^\w\s]
。
答案 1 :(得分:3)
正面和负面角色类别中原子之间的关系是不同的。在正数中,原子是ORed(匹配此OR),在负字符类中,元素是AND(不匹配此AND)。
因此,[\W\S]
匹配字母数字/下划线以外的字符,或者 - 如果找到 - 也匹配不等于空格的字符。 由于\W
匹配空白而\S
匹配任何非空格,因此[\W\S]
匹配任何字符。这就是a.gsub(/[\W\S]/,'')
返回空字符串的原因。
对于[^\w\s]
,它匹配任何不是字母数字/下划线且不是空格的字符。因此,它匹配任何非单词字符,没有空格字符([\W&&[^\s]]
构造的同义词)。请参阅rubular demo。
还有一个插图:
\W
是一个通用的速记字符类,匹配所有非单词(或匹配除“单词”以外的任何字符)字符。现在,除了;
之外,我们希望匹配所有非字字符。分号是非单词字符。我们该怎么办?我们可以使用具有相反类\w
- [^\w]
的否定字符类 - 并将;
添加到其中 - > [^\w;]
。此[^\w;]
将匹配任何非字和非;
字符。