我希望不区分大小写匹配我的数组中的字符串TOKENS
,在另一个字符串的开头跟一个空格或行的结尾。
我的令牌数组看起来像:
2.4.0 :013 > TOKENS = ["m", "o"]
=> ["m", "o"]
当我尝试匹配数组中的每个元素时,它会找出错误的结果:
2.4.0 :009 > data_col = ["M", "b", "Mabc", "abc m b"]
=> ["M", "b", "Mabc", "abc m b"]
...
2.4.0 :015 > data_col.select{|string| string =~ /^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i }
=> ["M", "b"]
这匹配“M”和“b”条目,即使“b”没有出现在我的TOKENS列表中。如何修改我的正则表达式,以便只匹配正确的值“M”?
我正在使用Ruby 2.4。
答案 0 :(得分:3)
我会用:
TOKENS = ["m", "o"]
DATA_COL = ["M", "b", "Mabc", "abc m b"]
RE = /^(?:#{Regexp.union(TOKENS).source})(?: |$)/i
DATA_COL.select{ |string| string[RE] }
# => ["M"]
稍微分解一下:
Regexp.union(TOKENS).source # => "m|o"
/^(?:#{Regexp.union(TOKENS).source})(?: |$)/i # => /^(?:m|o)(?: |$)/i
/^[#{Regexp.union(TOKENS)}]([[:space:]]|$)/i
在循环中不是一个好主意。每次通过你强迫Ruby创建模式;效率在循环内部很重要,尤其是大循环,因此在循环外创建模式然后引用内部模式。
下一个问题是Regexp.union
有一个应该匹配的正确案例的概念:
Regexp.union(TOKENS).to_s # => "(?-mix:m|o)"
(?-mix:
部分是正则表达式引擎如何记住模式的标志。当图案嵌入另一个图案时,他们会继续知道他们应该寻找什么,导致我们咬牙切齿并哭泣:
/#{Regexp.union(TOKENS)}/i # => /(?-mix:m|o)/i
尾随i
告诉它应该忽略大小写的模式,但嵌入的i
没有设置,所以它是尊重案例。这就是破坏你的模式的原因。
修复是在嵌入时使用source
,就像我上面那样。
有关详细信息,请参阅正则表达式“options”部分。