首页 > 解决方案 > Ruby 动态填充 2 个 dim 数组

问题描述

我正在使用解析器来分析 SQL 代码,因此试图处理所有块注释。我提出了按索引处理正则表达式的解决方案,以查看它是否在注释块内,并为此尝试在下面的代码中填充 2 dim 数组,其中第二个元素将是字面意思,让我们说s。不确定这是否可行。我尝试了一颗宝石,但失败了。我的目标是让数组充满

all =[[9,'s'],[19,'s'],[24,'s']]
参考下面的例子。最终目标是处理遗留的 SQL 代码(很多......)以找到具有特定关键字的活动行。最好的

x = 'line:xss /*   */   /*   /*  CODE_Comment */  '
     puts x

    i = -1
    all = [[],[]]
    while i = x.index('/*',i+1)             
do   all << i   ####<@>>< how to add literal to second element ???
    end
    puts all  

标签: ruby

解决方案


您可以执行以下操作。

str = 'line:xss /*   */   /*   /*  CODE_Comment */  '

str.gsub(/\/\*/).with_object([]) { |_,a| a << [Regexp.last_match.begin(0), 's'] }
  #=> [[9, "s"], [19, "s"], [24, "s"]] 

步骤如下。

enum1 = str.gsub(/\/\*/)
  #=> #<Enumerator: "line:xss /*   */   /*   /*  CODE_Comment */  "
  #     :gsub(/\/\*/)>

如果您检查String#gsub的文档,您将看到当gsub有单个参数且没有块(该方法的第 4形式)时,它返回一个枚举器。奇怪的是,当以这种方式使用时,它与用其他子字符串替换子字符串无关。

enum1无非就是生成匹配:

enum1.next #=> "/*" 
enum1.next #=> "/*" 
enum1.next #=> "/*" 
enum1.next #=> StopIteration (iteration reached an end)

请参阅Enumerator#next。在继续之前,让我们重置枚举器:

enum1.rewind

请参阅Enumerator#rewind。下一个,

enum2 = enum1.with_object([])
  #=> #<Enumerator: #<Enumerator: "line:xss /*   */   /*   /*  CODE_Comment */  "
  #     :gsub(/\/\*/)>:with_object([])> 
enum2.next #=> ["/*", []] 
enum2.next #=> ["/*", []] 
enum2.next #=> ["/*", []] 
enum2.next #=> StopIteration (iteration reached an end) 
enum2.rewind

enum2(可以被认为是一个复合枚举器)现在生成它传递给块的元素。这些元素的值由块变量捕获,然后执行块计算。我们可以添加一些puts语句来检查计算的值。

enum2.each do |_,a|
  puts "\n_ = #{_}, a = #{a}"
  md = Regexp.last_match
  b= md.begin(0) 
  puts "md = #{md}, b = #{b}"
  a << [b, 's']
  puts "a = #{a}"
end
  #=> [[9, "s"], [19, "s"], [24, "s"]] 

并打印

_ = /*, a = []
md = /*, b = 9
a = [[9, "s"]]

_ = /*, a = [[9, "s"]]
md = /*, b = 19
a = [[9, "s"], [19, "s"]]

_ = /*, a = [[9, "s"], [19, "s"]]
md = /*, b = 24
a = [[9, "s"], [19, "s"], [24, "s"]]

我使用下划线(一个有效的局部变量)作为第一个块变量的占位符,向读者表明它没有用于块计算(一种常用的约定)。要构造数组,我们需要进行str匹配的字符串中的偏移量。为此,我们首先获取该MatchData匹配生成的实例(参见Regexp::last_match),然后使用LastMatch#begin方法获取匹配开始的偏移量。最后,我们将所需的 2 元素数组附加到a.

的值Regexp.last_match由全局变量 保存$~,因此有时使用该变量代替Regexp.last_match


推荐阅读