2011-07-24 8 views
39

文字列内の正規表現が出現するたびにMatchDataが必要です。これはMatch All Occurrences of a Regexで提案されているスキャン方法とは異なります。これは私に文字列の配列を与えるだけです(私は完全なMatchDataを必要とし、開始と終了の情報を取得するなど)。文字列内のRuby正規表現のすべての一致データを取得するにはどうすればよいですか?

input = "abc12def34ghijklmno567pqrs" 
numbers = /\d+/ 

numbers.match input # #<MatchData "12"> (only the first match) 
input.scan numbers # ["12", "34", "567"] (all matches, but only the strings) 

私が見落とした方法がいくつかあります。提案?

+0

各試合の開始位置と終了位置が必要です。しかし、それは私の質問とは無関係です。 MatchDataは理由のために存在しますか?私が最初の試合でそれを得ることができれば、すべての試合に役立つだろう。 –

+1

わかりました。私は、それぞれのマッチのために便利なパッケージに複数のものが欲しいです。 –

+0

あなたが好きなように必要なデータに一致するように、あなたが名前を付けたように便利なパッケージを用意しました。それともあなたが探しているものは何ですか? –

答えて

63

あなたは "トリック"

[#<MatchData "12">, #<MatchData "34">, #<MatchData "567">] 

あなたに

を与える

"abc12def34ghijklmno567pqrs".to_enum(:scan, /\d+/).map { Regexp.last_match } 

をしたいが、あります。

+1

ありがとうございます。これで私の人生は10倍も楽になりました。 – Linuxios

+0

これはapidock.comまたはこれに類するものでなければなりません。あなたは少なくとも10の新しい灰色の毛髪から私を救った:) – nex

+3

これのための組み込みのメソッドがないということは信じられない、私たちはこれのようなハックに頼らなければならない。 – Miscreant

8

私の現在のソリューションは、正規表現にeach_matchメソッドを追加することです:

class Regexp 
    def each_match(str) 
    start = 0 
    while matchdata = self.match(str, start) 
     yield matchdata 
     start = matchdata.end(0) 
    end 
    end 
end 

今、私にできること:

numbers.each_match input do |match| 
    puts "Found #{match[0]} at #{match.begin(0)} until #{match.end(0)}" 
end 

より良い方法がある教えてください。あなたは、各last_matchを得るために列挙子を構築するために、参照として

+0

これは、あなたが答えようとしている場合を除き、実際に元の質問に追加する必要があります。 –

+0

また、matchdata = self.match(str、start)は、これがエラーか意図的かどうかを知ることが難しいため、構造を維持するのが非常に難しいと考えられています。 –

+4

質問に追加する理由は何ですか?それは答えです。私はちょうど良い答えがあることを望んでいる、それは私が自分自身を受け入れるだけではなかった理由です。より良い答えが見つからなければ、最終的にはそれを答えとしてマークします。 –

6

私は、それぞれのGoogle検索を経由してコードを利用できるようにするだけの場合にはそれをここに入れます:requstedとして

input = "abc12def34ghijklmno567pqrs" 
numbers = /\d+/ 
input.gsub(numbers) { |m| p $~ } 

結果は次のとおりです。

⇒ #<MatchData "12"> 
⇒ #<MatchData "34"> 
⇒ #<MatchData "567"> 

Detailed explanation

私は誰もがRubyの標準ライブラリに含まれて素晴らしい StringScannerクラス言及していない驚いて
+0

これをやってくれてありがとう、とにかく実際に 'gsub'を実際に使いたかったので、完璧に動作します。 – rjh

+0

これを行うのではなく、あなたがしようとしているのがMatchDataを取得するのであれば、 'scan'を使います。意思をより明確に伝えます。 – Justin

+0

@justin、*明示的には、 'scan'はMatchDataのものではなく、一致した文字列の配列を返します。 – DeFazer

0
input = "abc12def34ghijklmno567pqrs" 
n = Regexp.new("\\d+") 
[n.match(input)].tap { |a| a << n.match(input,a.last().end(0)+1) until a.last().nil? }[0..-2] 

=> [#<MatchData "12">, #<MatchData "34">, #<MatchData "567">] 
0

require 'strscan' 

s = StringScanner.new('abc12def34ghijklmno567pqrs') 

while s.skip_until(/\d+/) 
    num, offset = s.matched.to_i, [s.pos - s.matched_size, s.pos - 1] 

    # .. 
end 

いいえ、それはあなたのMatchDataオブジェクトを与えるものではありませんが、それはあなたにindex-を与えずに文字列へのベースのインターフェイス。

関連する問題