我想不区分大小写地匹配我的数组 TOKENS
中的一个字符串,它位于另一个字符串的开头,后跟一个空格或行尾。
我的 token 数组如下所示:
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”没有出现在我的 token 列表中。如何修改我的正则表达式以便只匹配正确的值“M”?
我正在使用 Ruby 2.4。
最佳答案
我会使用:
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”部分。
关于arrays - 如何在另一个字符串的开头匹配数组中的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44296269/