【问题标题】:Sub-pattern in regex can't be dereferenced?不能取消引用正则表达式中的子模式?
【发布时间】:2013-09-06 10:34:27
【问题描述】:

我遵循 Perl 脚本从日志中提取数字。当我在变量中定义子模式时,?: 的非捕获组似乎不起作用。只有当我在正则表达式模式或$number 中的子模式中省略分组时,它才有效。

#!/usr/bin/perl
use strict;
use warnings;

my $number = '(:?-?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[Ee][+-]?\d+)?)';
#my $number = '-?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[Ee][+-]?\d+)?';

open(FILE,"file.dat") or die "Exiting with: $!\n";
while (my $line = <FILE>) {
        if ($line =~ m{x = ($number). y = ($number)}){
        print "\$1= $1\n";
        print "\$2= $2\n";
        print "\$3= $3\n";
        print "\$4= $4\n";
    };
}
close(FILE);

此代码的输出如下所示:

$1= 12.15
$2= 12.15
$3= 3e-5
$4= 3e-5

输入:

asdf x = 12.15. y = 3e-5 yadda

那些双倍的输出是不想要的。

这是因为m{} 样式与正则表达式的常规m// 模式形成对比吗?我只知道在我的正则表达式中获取变量(子字符串)的前一种风格。我只是注意到这一点用于反向引用,所以元字符可能还有其他差异吗?

【问题讨论】:

  • It seems that the non-capturing group with :? isn't working 这不是非捕获组,它是一个常规括号。
  • 你应该澄清你的问题。您无法引用的这个子模式是什么?你的代码像你说的那样工作,有问题吗?
  • 是的,代码就像我说的那样工作,但我不想要那些加倍的组。对不起,不清楚的问题。

标签: regex perl backreference metacharacters


【解决方案1】:

您用于正则表达式的分隔符不会导致任何问题,但以下是:

(:?-?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[Ee][+-]?\d+)?)
 ^^
Notice this isn't a capturing group, it is an optional colon :

可能是拼写错误,但它造成了麻烦。

编辑:看起来这不是拼写错误,我替换了正则表达式中的变量,我得到了这个:

x = ((:?-?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[Ee][+-]?\d+)?)). y = ((:?-?(?:(?:\d+\.?\d*)|(?:\.\d+))(?:[Ee][+-]?\d+)?))
    ^^           first and second group               ^^      ^^    third and fourth grouop                     ^^

如您所见,第一个和第二个捕获组正在捕获完全相同的东西,第三个和第四个捕获组也在发生同样的事情。

【讨论】:

  • 我也在考虑错字,但是在正则表达式中使用大量 ?: 组时,将其称为 :? 会非常奇怪。
  • 等待 OP 的澄清。我什至不明白他在问什么。
  • 谢谢。我真的很愚蠢的错字...我认为通过将子正则表达式字符串保存到变量中并在正则表达式中使用它会有所不同。好像不是这样的。
【解决方案2】:

你会踢自己的......

你的正则表达式读作:

capture {
 maybe-colon
 maybe-minus
 cluster {     (?:(?:\d+\.?\d*)|(?:\.\d+))
  cluster {    (?:\d+\.?\d*)
   1+ digits
   maybe-dot
   0+ digits
  }
  -or-
  cluster {    (?:\.\d+)
   dot
   1+digits
  }
 }
 maybe cluster {
   E or e
   maybe + or -
   1+ digets
 }             (?:[Ee][+-]?\d+)?
}

...这就是你要找的东西。

但是,当您执行实际的正则表达式时,您会:

$line =~ m{x = $number. y = $number})

(花括号会分散注意力......如果指定了ms,则可以使用任何\W)

这要求capture 无论$number 中定义的正则表达式是......它本身就是一个capture.... 因此$1$2 是同一件事.

只需从$number 或正则表达式行中删除捕获括号。

【讨论】:

  • 就像我在问题中写的It's only working when I leave out the grouping in either the regex-pattern or the sub-pattern in $number. 问题是我不理解这种行为,因为我只想匹配每个条目一次。唯一的问题是:? 的错字,我确实为此自责...
  • Yes.... 因为$number 包含捕获,所以当您执行 '($number)' 时,您会执行 second 捕获 - 意思是 '$1' 和 ' $2' - 然后你稍后在正则表达式中重复'($number)',得到'$3' & '$4'。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多