我实现了一个脚本,该脚本将检查给定正则表达式模式的文件(或多个文件),并在文件包含任何匹配项时提醒用户。但是,我希望能够允许用户在文件中指定异常(即文件中不会被检查的部分)。我想要实现这个的方式是使用BEGIN:EXCEPTION和END:文件中的EXCEPTION标记。脚本现在的工作方式如下:
(假设文件内容在$ _中)
my $re_dirty = /hello world/; # Simple example
if($re_dirty) {
# alert that the pattern was found in the file
}
我尝试将此更改为以下内容:
my $re_dirty = /hello world/; # Simple example
my $begin_token = 'BEGIN:EXCEPTION';
my $end_token = 'END:EXCEPTION';
if($re_dirty && $_ !~ /${begin_token}.*${re_dirty}.*${end_token}) {
# alert that the patter was found and was not in an exception block
}
然而,这有明显的问题:
1.如果模式之前和之后存在异常但模式本身不在异常中,它将匹配
2.如果模式在文件中两次,它将不匹配,但只有它们在异常块中
3.可能更多的问题??
一些澄清说明:
1.例外情况可能跨越多行
2.每个文件可以有多个异常块。
答案 0 :(得分:3)
您可以在标量上下文中使用flip-flop (range operator):
if (/$begin/ .. /$end/) {
if (/$re_dirty/) {
# do stuff
}
}
范围运算符的这种特殊用法将返回false(作为语句),直到左侧返回true,之后它将返回true,直到右侧返回true。
当然,使用这种方法,您应该以逐行模式读取文件。但就内存使用而言,这是一种更好的方法。
修改强>
如果你想匹配这些块的多行匹配 ,你首先必须将相关行收集为多行字符串:
my @outside;
my $content;
while (<$file>) {
if ( /$begin/ .. /$end/ ) { # if inside tags
if (defined $content) { # if not empty
push @outside, $content; # store the scalar into array
undef $content; # reset variable
}
} else {
$content .= $_; # store into scalar
}
}
push @outside, $content if defined $content;
for my $portion (@outside) {
if ($portion =~ /$re_dirty/) { # check for multiline matches
# do stuff
}
}
答案 1 :(得分:1)
我会做这样的事情:
(my $portion = $_) =~ s/${begin}.*?${end}//gs; # reject anything inside begin/end blocks
if ($portion =~ $re_dirty) {
# do stuff
}
通过这种方式,您只能获得$ part的文件相关部分(那些在之外的BEGIN / END令牌)。然后你可以在相关部分进行标准的正则表达式匹配...
请注意使用&#39;?&#39;修饰符,以避免从第一个开始标记到最后结束标记的匹配...
答案 2 :(得分:0)
你可以为你的逻辑添加一个布尔值:
my $begin_token = 'BEGIN:EXCEPTION';
my $end_token = 'END:EXCEPTION';
my $bool = 0;
$bool = 1 if $begin_token;
$bool = 0 if $end_token
然后你可以测试$ bool是1还是0来跳过或不是代码的一部分