複数の一致がある正規表現があります。$1 、 $2 などを使用して、一致したグループにアクセスできることがわかりました。しかし、同じ一致したグループの複数の出現にアクセスするにはどうすればよいでしょうか?
以下のページをご覧ください。
http://rubular.com/r/nqHP1qAqRY
したがって、$1 は 916 を返し、$2 は NIL を返します。229885 にアクセスするにはどうすればよいですか? $1[1] に似たものはありますか?
複数の一致がある正規表現があります。$1 、 $2 などを使用して、一致したグループにアクセスできることがわかりました。しかし、同じ一致したグループの複数の出現にアクセスするにはどうすればよいでしょうか?
以下のページをご覧ください。
http://rubular.com/r/nqHP1qAqRY
したがって、$1 は 916 を返し、$2 は NIL を返します。229885 にアクセスするにはどうすればよいですか? $1[1] に似たものはありますか?
まず、xml ベースのデータを正規表現だけで解析するのは得策ではありません。代わりに、nokogiri などの xml ファイルを解析するためのライブラリを使用します。
ただし、このアプローチを使用することが確実な場合は、次のことを知っておく必要があります。正規表現エンジンは、(満足のいく) 一致が得られるとすぐに停止します。したがって、1 つの正規表現呼び出しから文字列内のすべての可能な一致を取得することを期待することはできません。既に発生した各一致の後に、新しい正規表現一致を適用して文字列を反復処理する必要があります。あなたはそのようにすることができます:
# ruby 1.9.x version
regex = /<DATA size="(\d+)"/
str = your_string # Your string to be parsed
position = 0
matches = []
while(match = regex.match(str,position)) do # Until there are no matches anymore
position = match.end 0 # set position to the end of the last match
matches << match[1] # add the matched number to the matches-array
end
この後、解析されたすべての数値はmatches
.
しかし、あなたのコメントは、あなたがルビー1.8.xを使用していることを示唆しているので、1.8.xで動作する別のバージョンをここに投稿します(これらのバージョンではメソッド定義が異なります)。
# ruby 1.8.x version
regex = /<DATA size="(\d+)"/
str = your_string # Your string to be parsed
matches = []
while(match = regex.match(str)) do # Until there are no matches anymore
str = match.post_match # set str to the part which is after the match.
matches << match[1] # add the matched number to the matches-array
end
私のコメントを拡張してあなたの質問に答えるには:
値を配列に格納する場合は、ブロックを変更して反復する代わりに収集します。
> arr = xml.grep(/<DATA size="(\d+)"/).collect { |d| d.match /\d+/ }
> arr.each { |a| puts "==> #{a}" }
==> 916
==> 229885
これ|d|
は通常の Ruby ブロック パラメーター構文です。eachd
は一致する文字列で、そこから数値が抽出されます。機能的ではありますが、これは最もクリーンな Ruby ではありません。
パーサーを使用することをお勧めします。rexml のバージョンは次のようになることに注意してください (多かれ少なかれ):
require 'rexml/document'
include REXML
doc = Document.new xml
arr = doc.elements.collect("//DATA") { |d| d.attributes["size"] }
arr.each { |a| puts "==> #{a}" }
「XML」が実際の XML に変換されると、さらに有用なデータを取得できます。
doc = Document.new xml
arr = doc.elements.collect("//file") do |f|
name = f.elements["FILENAME"].attributes["path"]
size = f.elements["DATA"].attributes["size"]
[name, size]
end
arr.each { |a| puts "#{a[0]}\t#{a[1]}" }
~/Users/1.txt 916
~/Users/2.txt 229885
これは、正規表現のほとんどの実装では不可能です。(私の知る限り.NETだけがこれを行うことができます。)
次のような別の解決策を使用する必要がありscan()
ます。.