如何在另一个正则表达式中使用Regexp.union?

时间:2017-03-26 02:26:50

标签: ruby regex string

使用Ruby 2.4。我想通过说匹配任意数量的空格后跟一个出现在我的数组中的字母来创建一个正则表达式。所以我尝试了这个

Dim Active() As Variant
Dim i
ReDim Active(Range("G9:G24").Cells.Count)
For Each Zelle In Range("G9:G24")
If InStr(1, Zelle, "Active") <> 0 Then
Active(i) = Zelle.Offset(0, -4)
End If
i = i + 1
Next Zelle

 For i = LBound(Active) To UBound(Active)
 If Trim(Active(i)) <> "" Then
   Debug.Print Active(i)
   End If
  Next i
  End Sub

但正如您所看到的,尽管我的数组中的两个标记都没有结束,但两个标记都匹配。我如何重写我的正则表达式来解释这个问题?

2 个答案:

答案 0 :(得分:2)

解决方案

如果您对Regexen和插值不太谨慎,则会出现细微的错误。

你需要:

/[[:space:]]+(?:#{Regexp.union(LETTERS).source})$/i

以下是一个例子:

LETTERS = %w(a b).freeze
data = ['asdf f', 'sdfsdf x', 'test A', 'test a', 'testB', 'testb']
r = /[[:space:]]+(?:#{Regexp.union(LETTERS).source})$/i
# /[[:space:]]+(?:a|b)$/i
data.grep(r)
# ["test A", "test a"]

错误1

如果省略Regexp#source

r2 = /[[:space:]]+(?:#{Regexp.union(LETTERS)})$/i
# /[[:space:]]+(?:(?-mix:a|b))$/i
data.grep(r2)
# ["test a"]

请注意,Regexp.union区分大小写。当它被导入较大的正则表达式时,它的标志也会被导入:(a|b)区分大小写,因此它不匹配"test A"。这是一个相关主题:Interpolating regexes into another regex

错误2

如果省略a|b周围的parens:

r3 = /[[:space:]]+#{Regexp.union(LETTERS).source}$/i
# /[[:space:]]+a|b$/i
data.grep(r3)
# ["test A", "test a", "testB", "testb"]

空格只会在a之前考虑。 "testB"即使不应该匹配,也会匹配。

答案 1 :(得分:1)

<强>解决方案

Regexp.new("[[:space:]]+(#{Regexp.union(LETTERS).source})", Regexp::IGNORECASE)

您可以使用此正则表达式:

LETTERS = ["a","b"]
#=> ["a","b"]
regex = Regexp.new("[[:space:]]+#{Regexp.union(LETTERS)}", Regexp::IGNORECASE)
#=> /[[:space:]]+(?-mix:a|b)/i
data = ["asdf f", "sdfsdf x"]
#=> ["asdf f", "sdfsdf x"]
data.grep(regex)
#=> []
data = ["asdf f", "sdfsdf a"]
#=> ["asdf f", "sdfsdf a"]
data.grep(regex)
#=> ["sdfsdf a"]

但最内层的正则表达式不会忽略大小写。感谢@ EricDuminil的解决方案,很容易看出错误。