假设我有一个文件,其中包含我要匹配的行:

foo
quux
bar

在我的代码中,我有另一个数组:

foo
baz
quux

假设我们遍历文件,调用每个元素 $word, ,以及我们正在检查的内部列表, @arr.

if( grep {$_ =~ m/^$word$/i} @arr)

这工作正常,但在某种可能的情况下,我们有一个测试用例 fo. 在该文件中, . 在正则表达式中充当通配符运算符,并且 fo. 然后匹配 foo, ,这是不可接受的。

这当然是因为 Perl 正在将变量插入到正则表达式中。

问题:

如何强制 Perl 按字面意思使用变量?

有帮助吗?

解决方案

正确的答案是 - 不使用正则表达式。我并不是说正则表达式是坏的,但使用它们(什么等于)简单的平等检查是矫枉过正。

使用:grep { lc($_) eq lc($word) } @arr和快乐

其他提示

使用\Q...\E在Perl串直接逸出特殊符号变量值插值之后:

if( grep {$_ =~ m/^\Q$word\E$/i} @arr)

perlfaq6的回答 如何匹配变量中的正则表达式?:


我们不必将模式硬编码到匹配运算符(或任何与正则表达式一起使用的其他内容)中。我们可以将模式放入变量中以供以后使用。

匹配运算符是双引号上下文,因此您可以像双引号字符串一样插入变量。在本例中,您读取正则表达式作为用户输入并将其存储在 $regex 中。一旦您在 $regex 中获得了模式,就可以在匹配运算符中使用该变量。

chomp( my $regex = <STDIN> );

if( $string =~ m/$regex/ ) { ... }

$regex 中的任何正则表达式特殊字符仍然是特殊的,并且模式仍然必须有效,否则 Perl 会抱怨。例如,在此模式中有一个不成对的括号。

my $regex = "Unmatched ( paren";

"Two parens to bind them all" =~ m/$regex/;

当 Perl 编译正则表达式时,它将括号视为内存匹配的开始。当它找不到右括号时,它会抱怨:

Unmatched ( in regex; marked by <-- HERE in m/Unmatched ( <-- HERE  paren/ at script line 3.

根据我们的情况,您可以通过多种方式解决这个问题。首先,如果您不希望字符串中的任何字符特殊,可以在使用字符串之前使用 quotemeta 对它们进行转义。

chomp( my $regex = <STDIN> );
$regex = quotemeta( $regex );

if( $string =~ m/$regex/ ) { ... }

您还可以使用 \Q 和 \E 序列直接在匹配运算符中执行此操作。\Q 告诉 Perl 从哪里开始转义特殊字符,\E 告诉 Perl 在哪里停止(更多细节请参见 perlop)。

chomp( my $regex = <STDIN> );

if( $string =~ m/\Q$regex\E/ ) { ... }

或者,您可以使用 qr//,即正则表达式引号运算符(有关更多详细信息,请参阅 perlop)。它引用并可能编译该模式,并且您可以将正则表达式标志应用于该模式。

chomp( my $input = <STDIN> );

my $regex = qr/$input/is;

$string =~ m/$regex/  # same as m/$input/is;

您可能还想通过在整个事情周围包裹一个 eval 块来捕获任何错误。

chomp( my $input = <STDIN> );

eval {
    if( $string =~ m/\Q$input\E/ ) { ... }
    };
warn $@ if $@;

或者...

my $regex = eval { qr/$input/is };
if( defined $regex ) {
    $string =~ m/$regex/;
    }
else {
    warn $@;
    }

<强> Quotemeta

返回EXPR与反斜杠所有非“字”的字符的值。

http://perldoc.perl.org/functions/quotemeta.html

我不认为你想在这种情况下,一个正则表达式,因为你是不匹配的模式。你要找的,你已经知道字符的文字序列。建立与所述值的散列相匹配,并使用该过滤@arr

 open my $fh, '<', $filename or die "...";
 my %hash = map { chomp; lc($_), 1 } <$fh>;

 foreach my $item ( @arr ) 
      {
      next unless exists $hash{ lc($item) };
      print "I matched [$item]\n";
      }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top