regexp匹配组,但该组的成员除外

时间:2016-01-09 08:23:34

标签: ruby regex

因此,有一些正则表达式与特定组匹配,如下所示:

/./ - Any character except a newline.
/./m - Any character (the m modifier enables multiline mode)
/\w/ - A word character ([a-zA-Z0-9_])
/\s/ - Any whitespace character

在红宝石中:

/[[:punct:]]/ - Punctuation character
/[[:space:]]/ - Whitespace character ([:blank:], newline, carriage return, etc.)
/[[:upper:]]/ - Uppercase alphabetical

所以,这是我的问题:我如何获得正则表达式来匹配这样的组,但是免除一个角色?

示例:

  • 匹配除问号
  • 之外的所有标点符号
  • 匹配除新行之外的所有空白字符
  • 除了" go" ... etc
  • 之外的所有单词

感谢。

3 个答案:

答案 0 :(得分:5)

您可以使用字符类减法。

Rexegg

  

语法[…&&[…]]允许您在多个字符类上使用逻辑AND,以确保所有字符都存在。与否定字符相交,如[…&&[^…]]中的 允许您从原始类中减去该类

考虑this code

s = "./?!"
res = s.scan(/[[:punct:]&&[^!]]/)
puts res

输出仅为./?,因为排除了!

使用前瞻限制(如sawa刚刚编写的那样)也是可能的,但是当你支持这个减法时不需要。当您需要限制一些较长的值(超过1个字符)时,需要前瞻。 在许多情况下,必须将前瞻锚定到单词边界以返回正确的结果。作为使用前瞻来限制标点符号的示例(单字符匹配通用模式):

/(?:(?!!)[[:punct:]])+/

这将匹配1个或多个标点符号,但只有!

puts "./?!".scan(/(?:(?!!)[[:punct:]])+/)代码将输出./?(请参阅demo

只要您需要使用单个字符进行限制,就可以使用字符类减法,这比使用前瞻更有效。

因此,第三种场景正则表达式必须如下:

/\b(?!go\b)\w+\b/
        ^^

如果你写/(?!\bgo\b)\b\w+\b/,正则表达式引擎将检查输入字符串中的每个位置。如果您在开头使用\b,则只会检查字边界位置,并且该模式将产生更好的性能。另请注意,^^ \b非常重要,因为它会使正则表达式引擎检查整个单词go 。如果您将其删除,则只会限制不以go 开头的字词。

答案 1 :(得分:3)

将您要排除的内容放在比赛前面的负前瞻中。例如,

  • 要匹配除问号之外的所有标点符号,

    /(?!\?)[[:punct:]]/
    
  • 匹配"go"以外的所有字词,

    /(?!\bgo\b)\b\w+\b/
    

答案 2 :(得分:0)

这是一种有时有用的一般方法:

a = []
".?!,:;-".scan(/[[:punct:]]/) { |s| a << s unless s == '?' }
a #=> [".", "!", ",", ":", ";", "-"]

该区块的内容仅受您的想象力限制。