最简单的方法是将带引号的正则表达式定义为常量而不是列表:
use strict;
use warnings;
use autodie; # Will kill program on bad opens, closes, and writes
use feature qw(say); # Better than "print" in most situations
use constant {
LIST => qr/keyword1|keyword2|keyword3/, # Now a regular expression.
FILE_READ => 'file.txt', # You're defining constants, make this one too.
};
open my $read_fh, "<", FILE_READ; # Use scalars for file handles
# This isn't Java. You don't have to define "main" subroutine
while ( my $line = <$read_fh> ) {
chomp $line;
if ( $line =~ LIST ) { #Now I can use the constant as a regex
say $line;
}
}
close $read_fh;
顺便说一句,如果您不使用autodie,则打开文件并在未打开时失败的标准方法是使用以下or
语法:
open my $fh, "<", $file_name or die qq(Can't open file "$file_name": $!);
如果您必须使用列表作为常量,那么您可以使用join
来制作正则表达式:
use constant LIST => qw( keyword1 keyword2 keyword3 );
...
my $regex = join "|", map LIST;
while ( my $line = <$file_fh> ) {
chomp $line;
if ( $line =~ /$regex/ ) {
say $line;
}
}
接受一个列表(在本join
例中是一个常量列表),并通过您给它的字符串或字符分隔每个成员。我希望您的关键字不包含特殊的正则表达式字符。否则,您需要引用这些特殊字符。
附录
我的 $regex = 加入'|' => 地图 +quotemeta,列表;– 扎伊德
谢谢扎伊德。我以前不知道这个quotemeta
命令。我一直在用\Q
and尝试各种事情\E
,但它开始变得太复杂了。
Zaid 所做的另一种方法:
my @list = map { quotemeta } LIST;
my $regex = join "|", @list;
该地图对于初学者来说有点难以理解。map
接受每个元素LIST
并针对它运行quotemeta命令。这将返回我分配给的列表@list
。
想象:
use constant LIST => qw( periods.are special.characters in.regular.expressions );
当我运行时:
my @list = map { quotemeta } LIST;
这将返回列表:
my @list = ( "periods\.are", "special\.characters", "in\.regular\.expressions" );
现在,句点是文字句点,而不是正则表达式中的特殊字符。当我运行时:
my $regex = join "|", @list;
我得到:
$regex = "periods\.are|special\.characters|in\.regular\.expressions";
这是一个有效的正则表达式。