Ruby将动态(循环)添加到Regexp.union中。简单的字符串复制不起作用

时间:2018-08-28 17:31:11

标签: ruby regex

我正在尝试向Regexp.union命令中添加逻辑,以便可以从元素数量可能不同的数组中构建逻辑。在我的示例中,案例1正常,然后我尝试复制此字符串,但失败了,看起来Regexp.union在内部做得还多,然后我知道样本中的regURegU2匹配了仅作为to_s。我发现该类型为Regexp,但是,即使它完全可行,也找不到如何转换它的方法。是否有可能实现。我还开始用case#3在循环中使用本机union,但也遇到了麻烦。 Tx红宝石大师!

RegexData = ['alpha', 'bravo', 'charlie']
line = ' the alpha alphaaaa  asdfdsaf bravo'

###1 Regex.Join with fix number of elements Works OK
regU = Regexp.union(/#{RegexData[0].chomp}/ix, /#{RegexData[1].chomp}/ix, /#{RegexData[2].chomp}/ix )
pos1 = line.enum_for(:scan, regU).map { Regexp.last_match.begin(0) } 
puts '...1  regU: ' +  regU.to_s.length.to_s + '  ' +  regU.to_s     
puts 'scan1: ' + pos1.to_s      
p regU.instance_of? String  ## not string
p regU.instance_of? Array   ## not Array   
p regU.instance_of? Class    ## still not
p regU.class      ## Regexp  !!!!!!
puts 



###2 loop with fixing regex format,  no results , even regex match as string!!!!!!!!!!
regU2 = '(?-mix:'
RegexData.each_with_index {|val, index|     
    if val == RegexData.last then valx = '(?ix-m:' + val.chomp + '))'    else    valx = '(?ix-m:' + val.chomp + ')|'  end
    regU2 << valx
    }
puts '...2  regU2: ' +  regU2.to_s.length.to_s + '  ' +  regU2.to_s 
pos2 = line.enum_for(:scan, regU2).map { Regexp.last_match.begin(0) } 
puts 'scan2: ' + pos2.to_s   


if regU.to_s == regU2.to_s  then puts  'Bingo to_s matched!!!! ' else puts 'xxxxxxxxxxxxxx' end    
if regU      == regU2       then puts  'Bingo      matched!!!! ' else puts 'xxxxxxxxxxxxxx' end    

1 个答案:

答案 0 :(得分:1)

Regexp::Union结合您的模式。如果提供了字符串,则使用该方法对它们进行转义。如果提供正则表达式,则选项将保留,并且不会转义任何字符:

regex_data = ['alpha', 'bravo', 'charlie', '1 + 1 = 2']
Regexp.union(regex_data)
#=> /alpha|bravo|charlie|1\ \+\ 1\ =\ 2/

为防止正则表达式转义,或者要添加某些选项,必须首先将字符串转换为正则表达式。这可以通过使用Array#map来完成,将字符串提供给Regexp构造函数以及可选的一些正则表达式选项。使用Regexp::new方法默认情况下不会转义字符:

regexes = regex_data.map { |str| Regexp.new(str) }
Regexp.union(regexes)
#=> /(?-mix:alpha)|(?-mix:bravo)|(?-mix:charlie)|(?-mix:1 + 1 = 2)/

options = Regexp::EXTENDED | Regexp::IGNORECASE # See Regexp::new reference above
regexes = regex_data.map { |str| Regexp.new(str, options) }
Regexp.union(regexes)
#=> /(?ix-m:alpha)|(?ix-m:bravo)|(?ix-m:charlie)|(?ix-m:1 + 1 = 2)/

如果要使用带有转义的正则表达式字符的字符串,则必须首先将其传递通过Regexp::escape并将结果传递给构造函数。

regexes = regex_data.map { |str| Regexp.new(Regexp.escape(str), options) }
Regexp.union(regexes)
#=> /(?ix-m:alpha)|(?ix-m:bravo)|(?ix-m:charlie)|(?ix-m:1\ \+\ 1\ =\ 2)/

如果必须先chomp来考虑所有值,那么您就不必将字符串逻辑与正则表达式逻辑混在一起:

regex_data = regex_data.map(&:chomp)
# also written as: regex_data = regex_data.map { |str| str.chomp }
# or if you don't mind mutating your variable
regex_data.map!(&:chomp)