2017-05-31 19 views
1

私の配列の文字列と大文字と小文字を区別しない文字列、例えばTOKENSを、別の文字列の先頭にスペースまたは行の末尾に一致させたい他の文字列の先頭にある配列の文字列を一致させる方法

マイトークン配列は次のようになります。

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ている:私は私の配列から各要素を一致しようとすると、それは間違った結果を拾い出している

2.4.0 :013 > TOKENS = ["m", "o"] 
=> ["m", "o"] 

"b"はTOKENSのリストには表示されません。正規表現 "M"だけが一致するように正規表現を変更するにはどうすればよいですか?

私はRuby 2.4を使用しています。

答えて

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」を参照してください。

+0

さらにもう一つの問題は、元の正規表現が(Regexp.unionによって作成された)文字クラス(角括弧)の中に交替することです。 – Max

+0

これは '(?-mix:)'構造を持つときに 'b'が真に真を返すように見えるだけですが。 – Max

+0

ああ、それは '?-m'を' b'を含む文字クラスの中の文字範囲として解釈しています。 – Max

関連する問題