在两个可选标记之间找到子字符串

时间:2013-12-02 12:02:32

标签: ruby regex string

我试图从以下形式的字符串中提取子字符串:

dest=comp;jump

我正在寻找正则表达式来检索comp,但destjump都是可选的,在这种情况下,=;被省略。所以这些都是有效的配置:

dest=comp;jump
dest=comp
comp;jump
comp

destcompjump是任意字符串,但不包含等号或分号。

我设法提出的是以下内容:     (?:=)([^;=]*)(?:;) 不幸的是,当省略destjump时,它不起作用。

4 个答案:

答案 0 :(得分:2)

怎么样:

(?:.*=|^)([^;]+)(?:;|$)

您要搜索的字符串位于第1组。

答案 1 :(得分:0)

如果整行必须有这种形式,那么应该这样做:

if line.chomp =~ /\A(?:[^;=]+=)?([^=;]+)(?:;[^;=]+)?\z/
  puts $1
end

这会跳过像

这样的格式错误的行
"dest=dest=comp;jump;jump"

答案 2 :(得分:0)

我不会试图让一切都发生在一个正则表达式中。这条路使得阅读和维护更加困难。相反,我会使用case / when语句将其分解为更多原子测试:

如果你只想要comp,我会使用:

array = %w[
  dest=comp;jump
  dest=comp
  comp;jump
  comp
].map{ |str|

  case str
  when /.+=(.+);/, /=(.+)/, /(.+);/
    $1
  else
    str 
  end

}

array 
# => ["comp", "comp", "comp", "comp"]

when子句将复杂性分解为三个小测试,每个测试都很容易理解:

  1. 字符串是否同时包含'='';'?然后返回这两个字符之间的子字符串。
  2. 字符串是否有'='?然后返回最后一个字。
  3. 字符串是否有';'?然后返回第一个单词。
  4. 回复这个词。
  5. 如果您需要知道正在返回哪些条款,则需要更多代码:

    %w[
      dest=comp;jump
      dest=comp
      comp;jump
      comp
    ].each{ |str|
    
      dest, comp, jump = case str
                         when /(.+)=(.+);(.+)/
                           [$1, $2, $3]
                         when /(.+)=(.+)/
                           [$1, $2, nil]
                         when /(.+);(.+)/
                           [nil, $1, $2]
                         else
                           [nil, str, nil]
                         end
    
      puts 'dest="%s" comp="%s" jump="%s"' % [dest, comp, jump]
    }
    
    # >> dest="dest" comp="comp" jump="jump"
    # >> dest="dest" comp="comp" jump=""
    # >> dest="" comp="comp" jump="jump"
    # >> dest="" comp="comp" jump=""
    

答案 3 :(得分:0)

我只是尝试将表达式分成两部分,以便更容易理解发生的事情:

string = 'dest=comp;jump'
trimming_regexp = [/.*=/, /;.*/]
trimming_regexp.each{|exp| string.slice!(exp)}