在Ruby中分组正则表达式

示范文本

outline: 4 0 corner: 1 347980000 -2540000 0 corner: 2 347980000 -20320000 0 corner: 3 482600000 -20320000 0 corner: 4 482600000 -2540000 0 outline: 4 1 corner: 1 0 -2540000 0 corner: 2 345440000 -2540000 0 corner: 3 345440000 -20320000 0 corner: 4 0 -20320000 0 outline: 8 2 corner: 1 0 0 0 corner: 2 0 35560000 0 corner: 3 53340000 35560000 0 corner: 4 53340000 76200000 0 corner: 5 449580000 76200000 0 corner: 6 449580000 30226000 0 corner: 7 482600000 30226000 0 corner: 8 482600000 0 0 outline: 4 3 corner: 1 0 38100000 0 corner: 2 50800000 38100000 0 corner: 3 50800000 76200000 0 corner: 4 0 76200000 0 outline: 4 4 corner: 1 482600000 76200000 0 corner: 2 482854000 31750000 0 corner: 3 450850000 31750000 0 corner: 4 450850000 76200000 0 

/^\s+corner:\s*(\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/m捕获角的所有值。

/^\s*outline:\s*(\d+)\s+(\d+)$.*?\s+corner:\s*(\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/m捕获所有轮廓,但仅捕获每个轮廓的第一个角。

/^\s*outline:\s*(\d+)\s+(\d+)$.*?(^\s+corner:\s*(\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)$).*?/m与第二个相同,但看起来像这样:

 4 0 corner: 1 347980000 -2540000 0 1 347980000 -2540000 0 

我试图让它捕捉所有的轮​​廓和相关的角落。 它显然没有正确分组 – 任何建议?

谢谢 ;-)

由于您想要的捕获数量不同(可能没有限制),因此您无法在一个正则表达式中执行此操作。 String#scan #scan在这种情况下派上用场。

 text.scan(/^\s*outline:\s*(\d+)\s+(\d+)\n(.*?)(?:\n\n|\z)/m) .map{|a, b, corners| [a, b, corners.scan(/^\s+corner:\s*(\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/)]} 

会给你:

 [["4", "0", [["1", "347980000", "-2540000", "0"], ["2", "347980000", "-20320000", "0"], ["3", "482600000", "-20320000", "0"], ["4", "482600000", "-2540000", "0"]]], ["4", "1", [["1", "0", "-2540000", "0"], ["2", "345440000", "-2540000", "0"], ["3", "345440000", "-20320000", "0"], ["4", "0", "-20320000", "0"]]], ["8", "2", [["1", "0", "0", "0"], ["2", "0", "35560000", "0"], ["3", "53340000", "35560000", "0"], ["4", "53340000", "76200000", "0"], ["5", "449580000", "76200000", "0"], ["6", "449580000", "30226000", "0"], ["7", "482600000", "30226000", "0"], ["8", "482600000", "0", "0"]]], ["4", "3", [["1", "0", "38100000", "0"], ["2", "50800000", "38100000", "0"], ["3", "50800000", "76200000", "0"], ["4", "0", "76200000", "0"]]], ["4", "4", [["1", "482600000", "76200000", "0"], ["2", "482854000", "31750000", "0"], ["3", "450850000", "31750000", "0"], ["4", "450850000", "76200000", "0"]]]] 

如果你想要数字而不是字符串,

 text.scan(/^\s*outline:\s*(\d+)\s+(\d+)\n(.*?)(?:\n\n|\z)/m) .map{|a, b, corners| [a.to_i, b.to_i, corners.scan(/^\s+corner:\s*(\d+)\s+(-?\d+)\s+(-?\d+)\s+(\d+)/).map{|a| a.map(&:to_i)}]} 

会给你:

 [[4, 0, [[1, 347980000, -2540000, 0], [2, 347980000, -20320000, 0], [3, 482600000, -20320000, 0], [4, 482600000, -2540000, 0]]], [4, 1, [[1, 0, -2540000, 0], [2, 345440000, -2540000, 0], [3, 345440000, -20320000, 0], [4, 0, -20320000, 0]]], [8, 2, [[1, 0, 0, 0], [2, 0, 35560000, 0], [3, 53340000, 35560000, 0], [4, 53340000, 76200000, 0], [5, 449580000, 76200000, 0], [6, 449580000, 30226000, 0], [7, 482600000, 30226000, 0], [8, 482600000, 0, 0]]], [4, 3, [[1, 0, 38100000, 0], [2, 50800000, 38100000, 0], [3, 50800000, 76200000, 0], [4, 0, 76200000, 0]]], [4, 4, [[1, 482600000, 76200000, 0], [2, 482854000, 31750000, 0], [3, 450850000, 31750000, 0], [4, 450850000, 76200000, 0]]]] 

我不确定我是否想知道用正则表达式扫描该文件的目的是什么。

但是你知道,使用除正则表达式之外的几乎任何技术都很容易解析。

事实上,只需稍微改变语法1,它就是一个很好的YAML文件:

 - outline: 4 0 - corner: 1 347980000 -2540000 0 - corner: 2 347980000 -20320000 0 - corner: 3 482600000 -20320000 0 - corner: 4 482600000 -2540000 0 - outline: 4 1 . . . . . . 

你去,一个完美组织的数据结构与一行Ruby:

  > pp YAML::load_file 'corners.yaml' [{"outline"=> [{"corner"=>"1 347980000 -2540000 0"}, {"corner"=>"2 347980000 -20320000 0"}, {"corner"=>"3 482600000 -20320000 0"}, {"corner"=>"4 482600000 -2540000 0"}]}, {"outline"=> [{"corner"=>"1 0 -2540000 0"}, {"corner"=>"2 345440000 -2540000 0"}, {"corner"=>"3 345440000 -20320000 0"}, {"corner"=>"4 0 -20320000 0"}]}, {"outline"=> [{"corner"=>"1 0 0 0"}, {"corner"=>"2 0 35560000 0"}, {"corner"=>"3 53340000 35560000 0"}, {"corner"=>"4 53340000 76200000 0"}, {"corner"=>"5 449580000 76200000 0"}, {"corner"=>"6 449580000 30226000 0"}, {"corner"=>"7 482600000 30226000 0"}, {"corner"=>"8 482600000 0 0"}]}, {"outline"=> [{"corner"=>"1 0 38100000 0"}, {"corner"=>"2 50800000 38100000 0"}, {"corner"=>"3 50800000 76200000 0"}, {"corner"=>"4 0 76200000 0"}]}, {"outline"=> [{"corner"=>"1 482600000 76200000 0"}, {"corner"=>"2 482854000 31750000 0"}, {"corner"=>"3 450850000 31750000 0"}, {"corner"=>"4 450850000 76200000 0"}]}] 

1.现在我使用了vim(1)正则表达式来转换文件:%s/^ */&- /