如果字符不属于数组,如何指定匹配?

时间:2017-11-07 03:52:59

标签: arrays ruby regex ruby-2.4

我在指定&#34时遇到问题;下一个字符不应该来自这组字符"在我的正则表达式。我有

TOKENS = [":", ".", "'"]
"01:39\t" =~  /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
 #=> nil

由于"\t"不属于我的TOKENS数组,我认为上面应该匹配,但事实并非如此。如何调整我的正则表达式,特别是这部分

^#{Regexp.union(TOKENS)}

说该字符不应该是这个数组的一部分吗?

2 个答案:

答案 0 :(得分:0)

你需要围绕"而不是"正则表达式的一部分。

>> TOKENS = [":", ".", "'"]
>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/
>> "01:39\t" =~ regex
#=> nil

然而:

>> regex = /\b0\d[#{Regexp.union(TOKENS)}]\d\d[^#{Regexp.union(TOKENS)}]/
# Add brackets                            here^                and here^
>> "01:39\t" =~ regex
#=> 0

答案 1 :(得分:0)

您的/\b0\d[#{Regexp.union(TOKENS)}]\d\d^#{Regexp.union(TOKENS)}/模式最终会显示为

/(?-mix:\b0\d[(?-mix::|\.|')]\d\d^(?-mix::|\.|'))/
             ^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^

此处,正则表达式对象是具有禁用的多行,不区分大小写和自由间距模式的修改器组。最后一个^是行锚的开始,它就会破坏整个正则表达式,将它变成一个永远不匹配任何字符串的模式。

仅使用#{Regexp.union(TOKENS)}字符类括号包装[...]是不够的,您需要使用 .source 属性来摆脱{{ 1}}因为您不想否定(?-mix:...)mi但是,您无法使用x因为它会在字符类中添加Regexp.union char,所以它被视为文字字符(所以,你也会否定管道)。

您应该使用|定义分隔符序列,以转义应在正则表达式字符类中转义的所有字符,然后放在字符类方括号之间。

Ruby demo:

TOKENS.join().gsub(/[\]\[\^\\-]/, '\\\\\\&')

请参阅Rubular demo

请注意,TOKENS = [":", ".", "'", "]"] sep_rx = TOKENS.join().gsub(/[\]\[\^\\-]/, '\\\\\\&') puts sep_rx # => :.'\] rx = /\b0\d[#{sep_rx}]\d\d[^#{sep_rx}]/ puts rx.source # => \b0\d[:.'\]]\d\d[^:.'\]] puts "01:39\t" =~ rx # => 0 匹配.gsub(/[\]\[\^\\-]/, '\\\\\\&')][^\,并在其前面添加反斜杠。 -中的前4个反斜杠在替换模式中定义了一个字面反斜杠,'\\\\\\&'代表整个匹配