我正在尝试在if条件中展开字符串$searchCriteria
。有线索吗?
use strict;
my $argNum;
my $searchCriteria = "";
foreach $argNum (0 .. $#ARGV) {
$searchCriteria = $searchCriteria . "(\$_ =~ \/" . $ARGV[$argNum] . "\/i) && ";
}
$searchCriteria =~ s/&& $//;
#print $searchCriteria;
open IP, "<vm.txt" or die $!;
my @fileContents = <IP>;
foreach (@fileContents) {
if (${$searchCriteria}) {
print $_;
}
}
答案 0 :(得分:3)
如果您的搜索条件是正则表达式,则应准备自己编译的正则表达式。还要注意使用while循环(读取文件时)以避免过多的内存使用。如果您想要包含任何参数的行:
use strict;
use warnings;
my $searchRe = do {
my $searchCriteria = join '|', map "(?:$_)", @ARGV;
qr/$searchCriteria/i;
};
open my $fh, '<', 'vm.txt' or die $!;
while (<$fh>) {
print if m/$searchRe/;
}
close $fh;
或者如果你想要包含所有的行:
use strict;
use warnings;
my $searcher = do {
my @searchCriteria = map qr/$_/i, @ARGV;
sub {
# study; # study can help for long lines or lot of regular expressions
for my $re (@searchCriteria) {
return unless m/$re/;
}
return 1
}
};
open my $fh, '<', 'vm.txt' or die $!;
while (<$fh>) {
print if $searcher->();
}
close $fh;
(请注意,如果命令行参数是字符串而不是正则表达式,那么在\Q
周围可能需要\E
和$_
。)
最后,如果您希望提高许多搜索条件的速度,请使用Regexp::Optimizer。
use Regexp::Optimizer;
my $searchRe = do {
my $searchCriteria = join '|', map "(?:$_)", @ARGV;
Regexp::Optimizer->new->optimize(qr($searchCriteria)i);
};
答案 1 :(得分:1)
嗯......我不确定问题是什么......但不知怎的,我怀疑你需要qr //表达式(引用正则表达式)。
答案 2 :(得分:1)
看起来您想要评估该行是否包含@ARGV
中的所有参数。
我认为这可能更符合您所寻找的内容,也更适合perl人群。
use FileHandle;
use List::MoreUtil qw<all>;
my @regexes = map { qr/\L$_\E/i } @ARGV;
my $fh = FileHandle->new( '<vm.txt' );
die "Err: $!" unless $fh;
foreach my $line ( <$fh> ) {
print $line if all { $line =~ m/$_/i } @regexes;
}
当然,如果您想要进行一些压缩,因为您将在一次执行中一次又一次地执行测试,那么您可以为此创建一个子。
sub create_compound_test {
my $test_sub_text = "sub (_) {\n local \$_ = shift;";
foreach my $arg ( map { lc; } @_ ) {
$test_sub_text .= "\n return unless m/$arg/i;";
}
$test_sub_text .= "\n return 1;\n}";
my $test_sub = eval $test_sub_text;
Carp::croak "Could not create test:\n $test_sub_text - $@" if $@;
return $test_sub;
}
它与$_ =~ /blah/i && $_ =~ /blah2/ ...
那就是:
my $match_all = create_compound_test( @ARGV );
foreach ( <$fh> ) {
print if $match_all->();
}
但我可能更有可能这样做:
my $match_all = create_compound_test( @ARGV );
foreach ( grep { $match_all->(); } <$fh> ) {
print;
}
......甚至......
print foreach grep { $match_all->(); } <$fh>;
答案 3 :(得分:0)
你的问题是什么?也许您正在寻找ack?看起来你正试图eval一个字符串(通常是一个坏主意)。你应该至少使用qr //。也许是这样的:
my @regexs = map qr/(?i)$_/, @ARGV;
my $search = sub {
for my $re (@regexes) {
return unless /$re/;
}
return 1;
}
open IP, "<", "vm.txt" or die "Err: $!";
while (<IP>) {
print $_ if $search->();
}
这很容易改进。它没有经过测试。 YMMV。
答案 4 :(得分:0)
如果参数不是正则表达式,您可以构造一个可以正常工作的正则表达式。
这个想法是以下顺序:
(one|two|...)
(.*?)
(?!\1)
(one|two|...)
(.*?)
(?!\1|\2)
重复4-6,直到我们匹配所有条款。
所以构造它的代码是:
sub create_compound_match {
my @args = @_;
my $arg_limit = $#args;
my $expr = join( '|', map { lc; } @args );
my $neg_lookahead = join( '|', map { "\\$_" } 1..$arg_limit );
my $test = join( '.*?'
, "($expr)"
, ( map { '(?!'
. substr( $neg_lookahead, 0, 3 * $_ - 1 )
. ")($expr)"
} 1..$arg_limit
)
);
return qr/$test/i;
}
将以这种方式测试:
my $test = create_compound_match( @ARGV );
print foreach grep { /$test/i } <$fh>;
然而,这缺乏在命令行上传递正则表达式的能力@ARGV
可能等于qw,并且生成的正则表达式将很乐意匹配'a aa aaa aaaa'而不需要匹配b*
,因为“aa”!=“a”,所以负面前瞻就满足了。
答案 5 :(得分:0)
在查看Taking from Hynek -Pichi- Vychodil's answer之后,我意识到您可以使用List :: MoreUtil的all
子例程大大简化整个任务。我强烈推荐这个包。
use strict;
use warinings;
use List::MoreUtil qw/all/; # if installed (not a bad idea to get it if not)
my @regexen = map { qr/$_/i } @ARGV;
open my $fh, '<', 'vm.txt' or die $!;
foreach my $line (<$fh>) {
print $line if all { $line =~ $_ } @regexen;
};
close $fh;
将all
与any
合并为“或”匹配。
编辑:该死的,看起来Axeman发布的内容非常类似于此。伟大的思想相似,嗯? :)