如何在数组和grep中转义Perl正则表达式字符?

时间:2016-06-16 22:02:52

标签: arrays perl

我有两个问题,但也很容易回答。可能只是一个新手问题。谷歌几乎没有。

首先:如何在数组中放置Perl匹配运算符? 例如所有这些字符:

{}[]()^$.|*+?\

然后使用foreach?

其次,如果你有这个:

@array = qw(The $ quick ? brown | fox jumps over the lazy dog);

$string = "\? brown \|";

@new_array = grep(/$string/,@array);

如果在@array中正确查找$ string,如果@array是一些文本,例如包含美元符号,问号等?如果你搜索正则表达式字符,它将变成运算符。如果你这样做:

$string =~ s/\$/\$/gi; 

当然会有相同的结果。

提前致谢。

2 个答案:

答案 0 :(得分:3)

这里的问题是:

$string = "\? brown \|";

只是一种误导性的写作方式:

$string = "? brown |";

最好的修复方法是(选项1)根本不使用字符串,而是使用模式对象:

$pat = qr/\? brown \|/;

@new_array = grep(/$pat/,@array);

或(2)在创建模式时使用\Q“引用”字符串中的任何正则表达式元字符:

$string = "? brown |";

@new_array = grep(/\Q$string/,@array);

如果不这样做,您可以通过编写以下任何内容来确保您的字符串最终实际包含\? brown \|(而不仅仅是? brown |):

$string = "\\? brown \\|"; # option 3
$string = '\? brown \|';   # option 4
$string = "\Q\? brown \|"; # option 5

答案 1 :(得分:0)

除了合适的引用之外,搜索匹配的字符串不需要特别小心或转义。匹配模式只需要按字面意思进行转义即可进行转义,但如果存在附加引用则需要对其进行插值保护。有关引用的评论,请参见最后。

my @spec_ch = qw({ } [ ] ( ) ^ $ . | * + ? \ ); 
my @matched = grep { /\$|\?/ } @spec_ch;
print "@matched\n";

打印

$ ?

您的实际示例,仅缩短并使用foreach(有关grep的评论,请参见下文)。

my @patterns = ('\?', 'brown', '\|', 'fox');  # or  qw(\? brown \| fox); 
my $string   = '? brown |';                   # or   q(? brown |);
foreach my $patt (@patterns) {
    my ($match) = $string =~ m/($patt)/;
    print "$match\n" if $match;
}

打印

?
brown
|

您的示例转过来,使用包含单词和转义字符的模式

my $str = q(The $ quick ? brown | fox jumps over the lazy dog);
my $patt = qr(\? brown \|);  # or simply '\? brown \|'
my ($match) = $str =~ m/($patt)/;
print "$match\n";

打印

? brown |

您的 grep 示例的问题在于它尝试匹配相反的方式 - 变量$string用作模式,而数组中的单词是搜索匹配的字符串。

grep { $_ =~ m/$string/ } @array; 
# regex syntax: $text =~ m/$pattern/, so above $_ is string, $string is pattern

因此$_依次接受值The$quick(等),并搜索模式$string 在里面。上面的foreach示例可以解释您的想法。

双引号可能会出现问题,因为它们会进行插值,然后你必须进行额外的转义。使用单引号然后将转义的特殊字符带入正则表达式,无需任何解释。

运算符qwq不进行插值。请参阅Quote and Quote-like Operators in perlop