2014-10-14 2 views
2

У меня есть некоторые параметры, которые я должен сортировать по разным спискам. Префикс определяет, к какому списку должен принадлежать.Группирование регулярных выражений на основе предыдущего результата группировки

Я использую префиксы: c, a, n, o и дополнительный дефис (-), чтобы определить, нужно ли поместить его в включают л оно или исключить из списка.

Я использую регулярное выражение сгруппированных, как:

/^(-?)([o|a|c|n])(\w+)/ 

Но вот третья группа (\w+) не является универсальным, и оно должно быть на самом деле зависит от результата второго группы. Т.е., если префикс:

  • 'с' или 'а' ->/\w{3}/
  • 'о' ->/\w{2}/
  • еще ->/\w+/

Могу ли я сделать это с одно регулярное выражение? В настоящее время для этого я использую условие if.

Пример входных данных:

Действительно:

"-cABS", "-aXYZ", "-oWE", "-oqr", "-ncanbeanyting", "nstillanything", "a123", "-conT" (will go to c_exclude_list) 

Недопустимый:

"cmorethan3chars", "c1", "-a1234", "prefizisnotvalid", "somethingelse", "oABC" 

Выход: для каждого агд толчок к правильному списку, игнорировать недействительным.

c_include_list, c_exclude_list, a_include_list, a_exclude_list etc. 
+2

что вход и выход expecter – vks

+1

Ваш вопрос не имеет особого смысла в настоящее время. Ваше изменение просто отменяет ответы ниже. Какая черта - c_exclude_list? – nhahtdh

+0

Исправлено редактирование. – Zack

ответ

3

Вы можете использовать этот шаблон:

/(-?)\b([aocn])((?:(?<=[ac])\w{3}|(?<=o)\w{2}|(?<=n)\w+))\b/ 

Идея состоит в использовании lookbehinds, чтобы проверить предыдущий символ, не включив его в группу захвата.

+0

'(? nhahtdh

1

Начиная с версией 2.0, Рубин перешел от Oniguruma к Onigmo (развилков Oniguruma), который добавляет поддержку для условного регулярного выражения, среди других особенностей.

Таким образом, вы можете использовать следующее регулярное выражение, чтобы настроить шаблон на основе префикса:

^-(?:([ca])|(o)|(n))?(?(1)\w{3}|(?(2)\w{2}|(?(3)\w+)))$ 

Demo at rubular

+0

Нет, рубин не имеет поддержки сброса ветви или условного. – nhahtdh

+0

@nhahtdh, Ruby 2+ делает –

+0

http://rubular.com/r/J3GP5lTjPR –

0

Является ли единое, разумное изгибание регулярным выражением лучшим способом справиться с этой проблемой?

Вот более простой подход, который не использует регулярное выражение вообще. Я подозреваю, что он будет по крайней мере столь же эффективен, как и одно регулярное выражение, учитывая, что с последним вы все равно должны назначать соответствующие строки для своих соответствующих массивов. Я думаю, что он также лучше читается и будет легче поддерживать. Код ниже должен быть легко модифицирован, если я неправильно понял некоторые тонкости вопроса.

Код

def devide_em_up(str) 
    h = { a_exclude: [], a_include: [], c_exclude: [], c_include: [], 
     o_exclude: [], o_include: [], other_exclude: [], other_include: [] } 
    str.split.each do |s| 
    exclude = (s[0] == ?-) 
    s = s[1..-1] if exclude 
    first = s[0] 
    s = s[1..-1] if 'cao'.include?(first) 
    len = s.size 
    case first 
    when 'a' 
     (exclude ? h[:a_exclude] : h[:a_include]) << s if len == 3 
    when 'c' 
     (exclude ? h[:c_exclude] : h[:c_include]) << s if len == 3 
    when 'o' 
     (exclude ? h[:o_exclude] : h[:o_include]) << s if len == 2 
    else 
     (exclude ? h[:other_exclude] : h[:other_include]) << s 
    end 
    end 
    h 
end 

Пример

Давайте попробуем:

str = "-cABS cABT -cDEF -aXYZ -oWE -oQR oQT -ncanbeany nstillany a123 " + 
     "-conT cmorethan3chars c1 -a1234 prefizisnotvalid somethingelse oABC" 

devide_em_up(str) 
    #=> {:a_exclude=>["XYZ"], :a_include=>["123"], 
    # :c_exclude=>["ABS", "DEF"], :c_include=>["ABT"], 
    # :o_exclude=>["WE", "QR"], :o_include=>["QT"], 
    # :other_exclude=>["ncanbeany"], :other_include=>["nstillany"]} 
Смежные вопросы