Regex 在Perl';中插入变量时,如何转义元字符;谁是接线员?

Regex 在Perl';中插入变量时,如何转义元字符;谁是接线员?,regex,perl,variables,interpolation,Regex,Perl,Variables,Interpolation,假设我有一个包含我试图匹配的行的文件: foo quux bar 在我的代码中,我有另一个数组: foo baz quux 假设我们遍历该文件,调用每个元素$word,以及我们要检查的内部列表@arr if( grep {$_ =~ m/^$word$/i} @arr) 这是正确的,但是在文件中有一个测试用例fo.的情况下,作为正则表达式中的通配符操作,fo.然后匹配foo,这是不可接受的 这当然是因为Perl将变量插入正则表达式中 问题是: 如何强制Perl按字面意思使用变量?Quote

假设我有一个包含我试图匹配的行的文件:

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

foo
baz
quux
假设我们遍历该文件,调用每个元素
$word
,以及我们要检查的内部列表
@arr

if( grep {$_ =~ m/^$word$/i} @arr)
这是正确的,但是在文件中有一个测试用例
fo.
的情况下,
作为正则表达式中的通配符操作,
fo.
然后匹配
foo
,这是不可接受的

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

问题是:


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

Quotemeta

返回EXPR的值,并将所有非“word”字符反斜杠


使用
\Q..\E
在变量值插值后直接转义perl字符串中的特殊符号:

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

正确答案是-不要使用regexp。我并不是说regexp不好,但将它们用于(等于)简单的相等性检查是过分的

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

从的答案:


我们不必将模式硬编码到匹配操作符(或任何其他与正则表达式一起工作的东西)中。我们可以将该模式放在一个变量中供以后使用

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

chomp( my $regex = <STDIN> );

if( $string =~ m/$regex/ ) { ... }
当Perl编译正则表达式时,它将括号视为内存匹配的开始。当它找不到右括号时,它会抱怨:

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

我认为在这种情况下你不需要正则表达式,因为你没有匹配模式。您正在寻找您已经知道的字符的文字序列。使用要匹配的值构建一个散列,并使用该散列筛选
@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";
      }

打开我的$fh,'很好。正则表达式解决方案是旧代码和更复杂代码的残余。请参阅的可能重复。最后一个代码示例中的eval是否在“{…}”中捕获错误,或者“if($string=~m/\Q$input\E/)”中是否也有错误?eval将捕获其块中的所有错误,但就这个问题而言,它捕获了在匹配运算符中看到的显式代码中的错误。然后regexp将类似于“m/^fo\\E\.$/i”。请参见上的
\Q
元符号说明,特别注意
“abc\Qfoo\tbar$s\Exyz”
相当于
“abc”。quotemeta(“foo\tbar$s”)。“xyz”
chomp( my $regex = <STDIN> );
$regex = quotemeta( $regex );

if( $string =~ m/$regex/ ) { ... }
chomp( my $regex = <STDIN> );

if( $string =~ m/\Q$regex\E/ ) { ... }
chomp( my $input = <STDIN> );

my $regex = qr/$input/is;

$string =~ m/$regex/  # same as m/$input/is;
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 $@;
    }
 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";
      }