2016-10-25 82 views
0

我有一個模式列表,我想匹配一個字符串與這些模式,但我只需要匹配整個單詞,所以我正在尋找一種方法來動態地將單詞邊界插入到Regexp.union方法,但我錯過了一些東西。 這是我曾嘗試帶有詞邊界的正則表達式聯合

test_string = "lonewolf is lonely" 
pattern_list = ["lonely", "wolf", "jungle"] 
pattern_list.collect! { |pattern| pattern = "\b" + pattern + "\b"} 
patterncollection = Regexp.union(pattern_list) 
puts patterncollection 
puts test_string.scan(patterncollection) 

結果是空的,如果我打印模式集合我看到「\ B」不能正確轉義。 我不能直接在數組中插入「\ b」,因爲該列表會被動態檢索。 我嘗試了多個選項,但仍然沒有運氣。 不同的解決方法是值得歡迎的。

回答

2

最簡單的解決辦法是將移動聯盟之外的字邊界匹配器:

/\b(#{Regexp.union(pattern_list).source})\b/ 

▶ "lonewolf is lonely".scan /\b(#{Regexp.union(%w|lonely wolf jungle|).source})\b/ 
#⇒ [ 
# [0] [ 
#  [0] "lonely" 
# ] 
# ] 

另請參閱下面的顯著評論。基本上,它建議「使用源,除非你是絕對肯定的,你知道會發生什麼。 - 鐵皮人「。

我相應地更新了答案。

+0

完美!謝謝! – Jack

+0

在正則表達式中嵌入正則表達式時要小心,例如使用'Regexp.union'時。 ''foo'[/ FO#{Regexp.union(['O','B'])}/mix] #=> nil'但是'foo'[/ FO#{Regexp.union(['O ','B'])。source}/mix] #=>「foo」'。除非你絕對肯定你會知道會發生什麼,否則使用'source'。 –

+0

@TheTinMan謝謝,我更新了一個答案。這個特定的輸入沒有問題,但我完全同意值得提及角落案例。 – mudasobwa