根据先前的分组结果对正则表达式进行分组

时间:2014-10-14 14:53:52

标签: ruby regex

我有一些参数需要排序到不同的列表中。前缀确定它应属于哪个列表。

我使用类似:cano和其他连字符(-)的前缀来确定是否将其放入包含l它或排除列表。

我使用正则表达式分组为:

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

但是这里第三组(\w+)不是通用的,它实际上应该依赖于第二组的结果。即,如果前缀是:

  • 'c'或'a' - > /\w{3}/
  • 'o' - > /\w{2}/
  • 其他 - > /\w+/

我可以用一个正则表达式执行此操作吗?目前我使用if条件来执行此操作。

示例输入:

有效:

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

无效:

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

输出:对于每个arg推送到正确的列表,忽略无效。

c_include_list, c_exclude_list, a_include_list, a_exclude_list etc.

3 个答案:

答案 0 :(得分:3)

您可以使用此模式:

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

这个想法包括使用lookbehinds检查前一个字符而不将其包含在捕获组中。

答案 1 :(得分:1)

从版本2.0开始,Ruby已经从Oniguruma切换到Onigmo(Oniguruma的一个分支),这增加了对条件正则表达式以及其他功能的支持。

因此,您可以使用以下正则表达式根据前缀自定义模式:

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

Demo at rubular

答案 2 :(得分: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"]}