Ruby добавляет динамику (цикл) в Regexp.union. Простая репликация строк не работает - PullRequest
0 голосов
/ 28 августа 2018

Я пытаюсь добавить логику в мою команду Regexp.union, чтобы я мог построить ее из массива, где количество элементов может быть различным. В моем примере № 1 работает нормально, затем я попытался повторить эту строку, и она не удалась, похоже, Regexp.union делает немного больше, чем я знаю, regU и RegU2 в моем примере совпадают только как to_s. Я понял, что это тип Regexp, но не могу найти, как его преобразовать, если это вообще возможно. Возможно ли это сделать? Я также начал дело № 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 голосов
/ 28 августа 2018

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 ed, подумайте сначала об этом, чтобы вам не приходилось смешивать строковую логику с логикой регулярного выражения:

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...