2017-03-26 68 views
1

使用Ruby 2.4。我想創建一個正則表達式,通過匹配任意數量的空格後跟一個出現在我的數組中的字母。所以,我想這個如何在另一個正則表達式中使用Regexp.union?

LETTERS = ["a", "b"] 
# => ["a", "b"] 
data = ["asdf f", "sdfsdf x"] 
# => ["asdf f", "sdfsdf x"] 
data.grep(/(^|[[:space:]]+)[#{Regexp.union(LETTERS)}]$/i) 
# => ["asdf f", "sdfsdf x"] 

但你可以看到,儘管沒有標記在我的數組的一封信結束事實上,無論令牌得到匹配。我如何重寫我的正則表達式來解決這個問題?

回答

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的解決方案,很容易發現錯誤。

+0

謝謝,但這不是我所擁有的。我如何複製「/我」(不區分大小寫匹配)? 「\ s +」與「[[:space:]] +」不一樣「 – Dave

+0

@Dave'\ s +'類似於[[:space:]] +'但你說得對,它們是不一樣。我編輯忽略大小寫。 –

+0

'正則表達式:: IGNORECASE'仍然被內部正則表達式忽略。例如,你的正則表達式不匹配'「test A」'。 –

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

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

空間只會a之前予以考慮。即使它不應該,"testB"也會匹配。

相關問題