Techioz Blog

文字列内のすべてのパターンのインデックスを取得する方法

概要

string = "Jack and Jill went up the hill to fetch a pail of water. Jack fell down and broke his crown. And Jill came tumbling after. "
d = string.match(/(jack|jill)/i) # -> MatchData "Jill" 1:"Jill"
d.size # -> 1

これは、最初に出現したものとのみ一致します。 string.scan は部分的には機能しますが、一致したパターンのインデックスについては何も伝えません。

パターンの一致したすべてのインスタンスとそのインデックス (位置) のリストを取得するにはどうすればよいですか?

解決策

パターンの一致したすべてのインスタンスとそのインデックス (位置) のリストを取得するにはどうすればよいですか?

string = "Jack and Jill went up the hill to fetch a pail of water. Jack fell down and broke his crown. And Jill came tumbling after. "  
string.to_enum(:scan, /(jack|jill)/i).map do |m,|
  p [$`.size, m]
end

出力:

[0, "Jack"]
[9, "Jill"]
[57, "Jack"]
[97, "Jill"]

更新:

後読みの動作に注意してください。見た目の部分ではなく、実際に一致した部分のインデックスを取得します。

irb> "ab".to_enum(:scan, /ab/     ).map{ |m,| [$`.size, $~.begin(0), m] }
=> [[0, 0, "ab"]]
irb> "ab".to_enum(:scan, /(?<=a)b/).map{ |m,| [$`.size, $~.begin(0), m] }
=> [[1, 1, "b"]]