Regex 在perl中,是否有一种更简洁的方法来搜索多个模式,并用表达式替换每个模式
在perl中,我正在读取一行代码,并尝试使用一系列if语句将一组字符串替换为相应的表达式。例如:Regex 在perl中,是否有一种更简洁的方法来搜索多个模式,并用表达式替换每个模式,regex,perl,replace,Regex,Perl,Replace,在perl中,我正在读取一行代码,并尝试使用一系列if语句将一组字符串替换为相应的表达式。例如: my @shiftInstructions=("lsr", "lsl", "rol", "ror"); while (my $line = <>) { if ($line =~ /\$sh/) { my $r = int(rand(6)); $line =~ s/\$sh/$r/; } if ($line =~ /\$ish/) { my $r = $
my @shiftInstructions=("lsr", "lsl", "rol", "ror");
while (my $line = <>) {
if ($line =~ /\$sh/) {
my $r = int(rand(6));
$line =~ s/\$sh/$r/;
}
if ($line =~ /\$ish/) {
my $r = $shiftInstructions[rand(4)]
$line =~ s/\$ish/$r/;
}
}
my@shiftInstructions=(“lsr”、“lsl”、“rol”、“ror”);
while(我的$line=){
如果($line=~/\$sh/){
我的$r=int(兰特(6));
$line=~s/\$sh/$r/;
}
如果($line=~/\$ish/){
my$r=$shiftInstructions[rand(4)]
$line=~s/\$ish/$r/;
}
}
我不喜欢这种方法有很多原因。首先,它是重复的。我必须首先检查模式是否存在,如果存在,则执行函数生成替换值,然后替换。因此它既冗长又缓慢(每个模式搜索2个正则表达式,可能最终会搜索几十个模式字符串)
我想到了一个映射,其中许多代码映射到要执行的相应代码
我可以想象映射到一个字符串,然后使用eval,但是除了在运行时,我无法检查代码。有没有更干净的方法
我在regex中找到了execute选项。编写一组子例程来处理每个正则表达式,然后创建一个映射,怎么样
my %regexMap = (
"\$fn", &foundFunc,
"\$hw", &hex8,
"\$hb", &hex2,
"\$sh", &rand6,
"\$ish", &shiftInst,
);
while (my $line = <>) {
$line =~ s/(\$fn|\$hw|\$hb|\$sh|\$ish|)/$regexMap{$1}/e;
print $line;
}
my%regexMap=(
“\$fn”、&foundFunc、,
“\$hw”、&hex8、,
“\$hb”、&hex2、,
“\$sh”&rand6,
“\$ish”、&shiftInst、,
);
while(我的$line=){
$line=~s/(\$fn\$hw\$hb\$sh\$ish)/$regexMap{$1}/e;
打印$行;
}
在这些情况下,我经常创建某种数据结构来保存模式及其操作:
my @tuples = (
[ qr/.../, sub { ... } ]
[ ... ].
);
现在,无论我想尝试多少种模式,整个过程的内容都保持不变:
while( <> ) {
foreach $tuple ( @tuples ) {
$tuple->[1]() if /$tuple[0]/
}
}
但同样,它取决于输入、您可能希望匹配的实际子字符串数量(因此,交替中的分支数量)、您希望处理的行数,等等。关于如何处理apache日志文件,以及他们试图使事情更快的各种实验,有一个精彩的讨论。我已经忘记了所有的细节,但是非常小的调整在数千万行中产生了明显的差异
有趣的阅读:
- 也许这次谈话李>
my @tuples = (
[ qr/.../, sub { ... } ]
[ ... ].
);
现在,无论我想尝试多少种模式,整个过程的内容都保持不变:
while( <> ) {
foreach $tuple ( @tuples ) {
$tuple->[1]() if /$tuple[0]/
}
}
但同样,它取决于输入、您可能希望匹配的实际子字符串数量(因此,交替中的分支数量)、您希望处理的行数,等等。关于如何处理apache日志文件,以及他们试图使事情更快的各种实验,有一个精彩的讨论。我已经忘记了所有的细节,但是非常小的调整在数千万行中产生了明显的差异
有趣的阅读:
- 也许这次谈话李>
- OP的代码可以用以下形式编写
use strict;
use warnings;
use feature 'say';
my %regexMap = (
'$fn' => \&foundFunc,
'$hw' => \&hex8,
'$hb' => \&hex2,
'$sh' => \&rand6,
'$ish' => \&shiftInst,
);
my @keys = map { "\\$_" } keys %regexMap;
my $re = join('|', @keys);
while (<DATA>) {
chomp;
next unless /($re)/;
$regexMap{$1}->();
}
sub foundFunc { say 'sub_foundFunc' }
sub hex8 { say 'sub_hex8' }
sub hex2 { say 'sub_hex2' }
sub rand6 { say 'sub_rand6' }
sub shiftInst { say 'sub_shiftInst' }
__DATA__
$fn
$hw
$ac
$hb
$sh
$fn
$mf
$hb
$ish
$hw
OP的代码可以用以下形式编写
use strict;
use warnings;
use feature 'say';
my %regexMap = (
'$fn' => \&foundFunc,
'$hw' => \&hex8,
'$hb' => \&hex2,
'$sh' => \&rand6,
'$ish' => \&shiftInst,
);
my @keys = map { "\\$_" } keys %regexMap;
my $re = join('|', @keys);
while (<DATA>) {
chomp;
next unless /($re)/;
$regexMap{$1}->();
}
sub foundFunc { say 'sub_foundFunc' }
sub hex8 { say 'sub_hex8' }
sub hex2 { say 'sub_hex2' }
sub rand6 { say 'sub_rand6' }
sub shiftInst { say 'sub_shiftInst' }
__DATA__
$fn
$hw
$ac
$hb
$sh
$fn
$mf
$hb
$ish
$hw
这是一种糟糕的写作方式
$line =~ s/\$sh/ int(rand(6)) /e;
所以
$regexMap{$1}
现在返回引用。您希望调用引用的子对象,这可以使用$regexMap{$1}->()
完成
while(我的$line=){
$line=~s/(\$fn\$hw\$hb\$sh\$ish)/$regexMap{$1}->()/e;
打印$行;
}
$line =~ s/\$sh/ int(rand(6)) /e;
所以
$regexMap{$1}
现在返回引用。您希望调用引用的子对象,这可以使用$regexMap{$1}->()
完成
while(我的$line=){
$line=~s/(\$fn\$hw\$hb\$sh\$ish)/$regexMap{$1}->()/e;
打印$行;
}
这更加优雅,但您仍在处理大量正则表达式。我刚刚在正则表达式上找到了execute选项。我将编辑以添加我发现的内容,但如果有反对的理由,请让我知道。您可以根据需要进行调整。您没有询问如何选择要检查的模式集,在某个时刻您必须决定要检查的模式集。这更优雅,但您仍然在处理大量正则表达式。我刚刚在正则表达式上找到了execute选项。我将编辑以添加我发现的内容,但如果有反对的理由,请让我知道。您可以根据需要进行调整。你没有问如何选择要检查的模式集,在某个时候你必须决定要检查的模式集。这是行不通的。不管输入是什么,它都会调用每个子对象一次,而且只调用一次。即使你解决了这个问题,它仍然不能满足OP的要求,这是行不通的。不管输入是什么,它都会调用每个子对象一次,而且只调用一次。即使你解决了这个问题,它仍然不能满足OP的要求,这与你的要求相反。
my @shiftInstructions=("lsr", "lsl", "rol", "ror");
while (my $line = <>) {
if ($line =~ /\$sh/) {
my $r = int(rand(6));
$line =~ s/\$sh/$r/;
}
if ($line =~ /\$ish/) {
my $r = $shiftInstructions[rand(4)]
$line =~ s/\$ish/$r/;
}
print($line);
}
my @shiftInstructions = qw( lsr lsl rol ror );
while (my $line = <>) {
$line =~ s/\$sh/ int(rand(6)) /e;
$line =~ s/\$ish/ $shiftInstructions[rand(@shiftInstructions)] /e;
print($line);
}
my @shiftInstructions = qw( lsr lsl rol ror );
while (my $line = <>) {
$line =~ s/\$(sh|ish)/
if ( $1 eq "sh" ) { int(rand(6)) }
elsif ( $1 eq "ish" ) { $shiftInstructions[rand(@shiftInstructions)] }
/eg;
print($line);
}
my @shiftInstructions = qw( lsr lsl rol ror );
my %replacements = (
sh => sub { int(rand(6)) },
ish => sub { $shiftInstructions[rand(@shiftInstructions)] },
);
my $alt = join '|', map quotemeta, keys(%replacements);
my $re = qr/\$($alt)/;
while (my $line = <>) {
print $line =~ s/$re/ $replacements{$1}->() /reg;
}
my %regexMap = (
"\$fn", \&foundFunc,
"\$hw", \&hex8,
"\$hb", \&hex2,
"\$sh", \&rand6,
"\$ish", \&shiftInst,
);
while (my $line = <>) {
$line =~ s/(\$fn|\$hw|\$hb|\$sh|\$ish|)/ $regexMap{$1}->() /e;
print $line;
}