0

所以我目前被困在这个问题上: 1. 我声明一个常量列表,比如 LIST 2. 我想通读一个文件,我在 while 循环中逐行这样做,如果该行有一个关键字 from LIST,我打印这条线,或者用它来打印一些东西。

这是我目前拥有的:

use constant LIST => ('keyword1', 'keyword2', 'keyword3');
sub main{
    unless(open(MYFILE, $file_read)){die "Error\n"};
    while(<MYFILE>){
        my $line = $_;
        chomp($line);
        if($line =~ m//){#here is where i'm stuck, i want is if $line has either of the keywords
            print $line;
        }
    }
}

我应该在那个 if 语句中做什么来匹配我想要程序做的事情?我可以在没有$line变量并简单地使用的情况下这样做$_吗?我只使用 $line 是因为我认为 grep 会自动将 LIST 中的常量放入$_. 谢谢!

4

1 回答 1

2

最简单的方法是将带引号的正则表达式定义为常量而不是列表:

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命令。我一直在用\Qand尝试各种事情\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";

这是一个有效的正则表达式。

于 2013-09-10T01:35:16.747 回答