我有一个有多个匹配的正则表达式。我发现$ 1,$ 2等可以用来访问匹配的组。但是如何访问同一匹配组的多个出现?
请查看下面的rubular页面。
http://rubular.com/r/nqHP1qAqRY
所以现在$ 1给出916而$ 2给出NIL。我怎样才能访问229885?是否有类似$ 1 [1]左右的东西?
答案 0 :(得分:3)
首先,仅使用正则表达式解析基于xml的数据不是一个好主意。 而是使用库来解析xml文件,比如nokogiri。
但是如果您确定要使用此方法,则需要了解以下内容。 一旦获得(令人愉悦的)匹配,正则表达式引擎就会停止。所以你不能 期望从一个正则表达式调用获得字符串中所有可能的匹配, 你需要在之后使用新的正则表达式匹配来遍历字符串 每个已经发生的比赛。你可以这样做:
# 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
。
但是,既然你的评论暗示,你正在使用 ruby 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
答案 1 :(得分:1)
扩展我的评论并回答您的问题:
如果要将值存储在数组中,请修改块并收集而不是迭代:
> arr = xml.grep(/<DATA size="(\d+)"/).collect { |d| d.match /\d+/ }
> arr.each { |a| puts "==> #{a}" }
==> 916
==> 229885
|d|
是正常的Ruby块参数语法;每个d
是匹配的字符串,从中提取数字。它不是最干净的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
答案 2 :(得分:0)
在大多数正则表达式的实现中,这是不可能的。 (AFAIK只有.NET可以做到这一点。)
您必须使用scan()
Equivalent to Python’s findall() method in Ruby?来使用替代解决方案,例如 。