[英]Grep & Perl regex negative lookbehind not working
我想在grep + perl中使用正则表达式,以便在finally子句中选择未封闭的 Java语句。
我想出的模式应该选择所有.submitBacth(); 前面没有最后一个{
但是,由于返回了所有匹配项,因此背后的负面表情似乎并不正确或无法按预期工作。
myself@mymachine:~/Desktop$ grep -C 3 -P '(?s)(?<!finally\s\{.).*?\.submitBatch\(\)\;' ~/myfile.txt
范例文字(myfile.txt):
//sample text
batch.addToBatchUpdate(item1);
}
batch.submitBatch();
dao.update(item2);
//another text
} finally {
--
}
}
} finally {
impl.submitBatch();
test.close();
}
预期输出应为:
//sample text
batch.addToBatchUpdate(item1);
}
batch.submitBatch();
dao.update(item2);
//anotehr text
} finally {
我希望只看到第一个条目batch.submitBatch();。 但如您所见,两者都返回了。
在Perl中,您可以使用
$regex_new = /( (?:finally\s+\{\s+|.) )(\S+\.submitBatch\(\)\; ) /sx;
从文件中提取带有.submitBatch
子字符串。 如果第一个捕获组( $1
的内容) finally
开始于您,则可以忽略该匹配项(因为您想排除那些匹配项)。
关于您的原始正则表达式,
$regex = /( (?<!finally\s\{.) .*? \.submitBatch\(\)\; )/sx;
这里有什么问题? 它将比所需的匹配更多,并且将很难提取您要查找的匹配。
例如:
use feature qw(say state);
use strict;
use warnings;
use Term::ANSIColor;
my $str = do { local $/; <DATA> };
my $regex = /( (?<!finally\s\{.) .*? \.submitBatch\(\)\; )/sx;
$str =~ s/$regex/color_match( $1 )/ge;
say $str;
sub color_match {
state $i = 0;
state $colors = [qw[red green blue]];
return color( "bold " . $colors->[$i++] ) . $_[0] . color("reset");
}
__DATA__
... code ...
} finally {
impl.submitBatch();
test.close();
}
batch.addToBatchUpdate(item1);
}
batch.submitBatch();
dao.update(item2);
//another text
} finally {
impl.submitBatch();
test.close();
}
输出为:
因此,每个匹配以.submitBatch();
结尾.submitBatch();
但是负向后断言(?<!finally\\s\\{.)
对于g
修饰符的每次迭代都立即匹配。 例如,对于第一次迭代,它在文件的开头匹配,然后是.*?
匹配所有直到第一个.submitBatch();
这样就完成了第一次迭代(无需回溯)。 其他比赛也一样。
如果将$regex
替换$regex
$regex_new
,则输出将是:
现在很容易排除错误的匹配。 例如,可以使用e
修饰符:
$str =~ s/$regex/fix_missing_finally_clause( $1, $2)/ge;
其中(例如):
sub fix_missing_finally_clause {
if ($_[0] =~ /^finally/ ) {
return $_[0].$_[1];
}
else {
# Insert your edits here... for example:
return "finally {\n" . $_[0] . $_[1] . "\n\t}\n";
}
}
感谢Håkon的详细回答,但是我更喜欢使用grep的perl扩展名,因为我还有其他正则表达式,而且我不想在perl中重写所有脚本(我希望脚本尽可能整洁),即使可能更容易。 我终于设法用此修补程序修复了正则表达式,这也需要注意在方法签名和我感兴趣的方法之间进行查找。
我知道正则表达式选择太多,但是我不是专家,并且我对替代不感兴趣,因此只要有对我的匹配就足够了。
myself@mymachine:~$grep -Pzo '(?s)(?<=public|private|protected).(?<!finally).*?\.submitBatch\(\)\;' /tmp/test.java
method
//sample text
batch.addToBatchUpdate(item1);
}
batch.submitBatch();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.