如何使perl句柄模式“c ++”与grep相同?

时间:2012-12-07 12:55:19

标签: regex perl error-handling grep

这并不奇怪:

% perl -ne 'print if /c++/' foo
Nested quantifiers in regex; marked by <-- HERE in m/c++ <-- HERE / at -e line 1.

但是,有点:

% grep c++ foo
blah c++ blah

我不知道grep正在做什么来容纳++ - 但我在perl中也是如此。或者,至少,一些优雅的方式来处理这种情况;模式来自用户,他可能会看到grep c++有效,然后对perl失败感到惊讶。

我不想使用quotemeta;我的真实代码期望正则表达式模式(来自用户):

while ( my $pattern = shift @pat_list ) {
    my $regex = $opts{case} ? qr/$pattern/ : qr/$pattern/i;
    my @hits = grep { /$regex/ } @lines;

我想我可以检测到模式有错误然后恢复为quotemeta。但我似乎无法使用eval来捕获错误(因为它被视为语法错误?)。

4 个答案:

答案 0 :(得分:4)

shell命令grep至少知道它如何解释正则表达式的三种模式:作为基本RE(默认),作为扩展RE(如果使用-Eegrep调用)和Perl兼容的RE(如果使用-P调用)。对于习惯于Perl的RE引擎的人来说,基本RE的行为有点不同。 grep的文档说明了您的特定用例:

In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose
their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(,
and \).

这意味着调用grep c++ something.txt时没有元字符。

请注意,即使是Perl兼容的RE(由着名的库libpcre提供)也与Perl自己的RE引擎实现的不同。 Perl的引擎功能集在所有RE实现中都非常独特。但是来自libpcre的PCRE(Perl兼容的RE)至少非常相似并且也被广泛使用,例如在PHP,C ++(Boost)中,像grep这样的工具,和大多数其他编程语言一样。

话虽如此:我建议如果你想在Perl和grep中使用大多数RE,那么使用grep的Perl兼容模式,例如: grep --perl-regexp $yourRE $yourFile.txt。如果您允许任意用户输入,请务必注意shell引用!那是String::ShellQuote

答案 1 :(得分:1)

如果你想要grep兼容(POSIX)正则表达式,你可以使用POSIX::Regex。 (它不是标准模块,您可能需要使用cpan命令安装它。)

答案 2 :(得分:0)

我的问题的主要观点是错误的。这很好用:

#!/usr/bin/perl -w
use strict;
my $pattern = "c++";
my $regex;
eval { $regex = qr/$pattern/; };
warn "Error detected: $@" if $@;

我已要求删除我的问题。很抱歉浪费了你们所有的时间。

答案 3 :(得分:0)

perl -ne'打印if / c \ + \ + /'foo

在正则表达式中,“+”表示“一个或多个”。