你没有说你是想要真正的子字符串匹配,还是在单词边界处进行子字符串匹配。有区别。以下是尊重单词边界的方法:
str = "this is the string "
array = ["this is" ,"second element", "third element"]
pattern = /\b(?:#{ Regexp.union(array).source })\b/ # => /\b(?:this\ is|second\ element|third\ element)\b/
str[pattern] # => "this is"
str.gsub(pattern, '').squeeze(' ').strip # => "the string"
下面是 union 和 union.source 的情况:
Regexp.union(array) # => /this\ is|second\ element|third\ element/
Regexp.union(array).source # => "this\\ is|second\\ element|third\\ element"
source 在创建模式时以正则表达式更容易使用的形式返回连接的数组,而不会在模式中注入漏洞。考虑这些差异以及它们在模式匹配中可以做什么:
/#{ Regexp.union(%w[a . b]) }/ # => /(?-mix:a|\.|b)/
/#{ Regexp.union(%w[a . b]).source }/ # => /a|\.|b/
第一个创建一个单独的模式,具有自己的大小写、多行和空格尊重标志,将嵌入外部模式中。这可能是一个很难追踪和修复的错误,因此只有在您打算拥有子模式时才这样做。
另外,请注意如果您尝试使用会发生什么:
/#{ %w[a . b].join('|') }/ # => /a|.|b/
生成的模式中嵌入了一个通配符.,它会破坏你的模式,使其匹配任何东西。不要去那里。
如果我们不告诉正则表达式引擎遵守单词边界,那么可能会发生意外/不受欢迎/可怕的事情:
str = "this isn't the string "
array = ["this is" ,"second element", "third element"]
pattern = /(?:#{ Regexp.union(array).source })/ # => /(?:this\ is|second\ element|third\ element)/
str[pattern] # => "this is"
str.gsub(pattern, '').squeeze(' ').strip # => "n't the string"
在处理包含完整单词的子字符串时,从单词的角度来思考是很重要的。引擎不知道区别,所以你必须告诉它该做什么。不需要进行文本处理的人经常错过这种情况。