1

尝试应用以下正则表达式时遇到问题:

(1234).*?(abcd)?

到下面的字符串:

1234567abcd

我的期望是上面应该产生两个匹配:

  1. 1234
  2. A B C D

但是,这不起作用。您可能会建议“好吧,只需删除尾随?字符?” - 但我希望这第二种模式是可选的。

这是怎么做到的?

重申:

(1234).*?(abcd)

... 给出了想要的结果,但我搜索的字符串并不总是包含abcd.

如果有人想知道,这是一个大图问题的简化示例。如果需要,我会解释。

====

我认为这个问题需要进一步澄清。这是我在 ruby​​ 中尝试做的更完整的示例。

鉴于我的日志文件中的以下两个“篡改”行:

Aug 28 00:00:05 app-system-1 app-prod[7660]: Completed 200 OK in 150ms (Views: 24.6ms | ActiveRecord: 66.1ms)
Aug 28 00:05:06 app-system-1 app-prod[10639]: Completed 302 Found in 81ms (ActiveRecord: 74.6ms)

我试图在 ruby​​ 中编译一个正则表达式,如下所示:

d=Regexp.new('(?<timestamp>\w{1,3}\s\d{1,2}\s\d\d:\d\d:\d\d).*(?<in>in [0-9]*).*(?<views>Views: [0-9]*).*(?<activerecord>ActiveRecord: [0-9]*)')

显然,在某些情况下,“视图”文本将包含在内,而在其他行中,则不存在。

我希望能够做类似的事情:

v=d.match(line)
if !v.nil?
    puts v[:timestamp]+ " " + v[:in] + " " + v[:views] + " " + v[:activerecord]

这显然是一个不完整的例子,但希望这可以澄清。

4

5 回答 5

2

您没有具体说明您想要什么,至少没有明确说明,但我认为您需要以下内容:

  • ...1234567abcd...作为输入给出时,1234567abcd应该匹配,1234并且abcd应该被捕获。
  • ...1234567abce...作为输入给出时,1234应该匹配,1234应该被捕获。

如果是这样,您可以使用:

/(1234)(?:.*?(abcd))?/s

我讨厌使用贪婪修饰符。它用于避免匹配某些序列,但不能保证它不会。我会改用以下内容:

/
   (1234)
   (?:
      (?:(?!abcd).)*    # Safer than .*?
      (abcd)
   )?
/sx
于 2012-08-31T02:20:04.543 回答
1

类似于 ikegami 但我认为更简单:

/(1234)(?:(?!abcd).)*(abcd)?/
于 2012-08-31T03:30:37.367 回答
1

锚定正则表达式有效:

/(1234).*?(abcd)?$/
于 2012-08-31T02:18:15.447 回答
0

因为(a|)大致相当于(a)?我们可以使用:

(1234).*?(abcd|)

强制正则表达式引擎检查第abcd一个。可选规则的默认设置?是假设它不存在(相当于(|abcd))。此默认行为对于确保正则表达式终止(更快)很重要。

于 2012-08-31T02:14:12.497 回答
0

你真的应该分步进行。

if (my ($ts, $dur, $breakdown) = /
   ^
   (\w{3}[ ]\d{1,2}[ ]\d\d:\d\d:\d\d)
   .*?
   in[ ]([0-9]*)ms
   .*?
   \( ([^()]*) \)
/xs) {
   my %breakdown = map /^([^:]+): (.*)ms/, split /\s*\|\s*/, $breakdown;
   say join ', ',
      $ts,
      $dur,
      $breakdown{Views} // '--',
      $breakdown{ActiveRecord} // '--';
}
于 2012-08-31T04:22:29.227 回答