任何人都可以帮我解决这个正则表达式吗?我需要一个表达式,它将匹配最后不包含“Created”字符串的行。该脚本用于读取某些源代码的标题。
$string = "* JAN-01-2001 bugsbunny 1234 Created Module";
#$string = "* DEC-12-2012 bugsbunny 5678 Modified Module";
if($string =~ /^\*\s+(\w\w\w-\d\d-\d\d\d\d)\s+(\w+)\s+(\d+)\s+(?!Created)/){
print "$1\n$2\n$3\n$4\n";
} else {
print "no match\n";
}
当使用第一个$ string定义时,我需要匹配失败,因为它的末尾有“Created”一词。当使用第二个$ string定义时,它应该通过,我需要提取日期($ 1),用户($ 2),更改数字($ 3)和描述($ 4)。
上面的表达不起作用。有什么建议吗?
答案 0 :(得分:4)
关闭:
/^\*\s+(\w{3}-\d{2}-\d{4})\s+(\w+)\s+(\d+)\s+(?!.*Created)/
您需要在Created
之前允许任意数量的非换行符,因此.*
。
否则,在匹配\s+
时,正则表达式只会备份一个字符,因此以下文本为" Created"
,然后(?!Created)
将匹配。
见here;注意匹配如何在Created
之前停止一个空格。
答案 1 :(得分:1)
您可以使用的另一个技巧是使用禁用回溯的(?>...)
组。禁用回溯意味着使用+
或*
的任何表达式都会贪婪地吃掉它找到的任何内容,并且如果模式失败,它将永远不会回去尝试别的东西。这意味着“Created”之前的所有空格都被占用,因此正则表达式的(?!Created)
部分总是出现在正确的点上。
if($string =~ /^(?>\*\s+(\w\w\w-\d\d-\d\d\d\d)\s+(\w+)\s+(\d+)\s+)(?!Created)/){
print "$1\n$2\n$3\n";
} else {
print "no match\n";
}
这也有使你的正则表达式更快的额外好处。
这种方法不适用于各种问题,因为许多正则表达式需要能够回溯才能正确匹配。但它对这个很有用。
答案 2 :(得分:0)
另一个选项是split
并测试'Created'的描述:
use strict;
use warnings;
#my $string = "* JAN-01-2001 bugsbunny 1234 Created Module";
my $string = "* DEC-12-2012 bugsbunny 5678 Modified Module";
my ( undef, $date, $user, $change, $desc ) = split ' ', $string, 5;
if ( $desc !~ /^Created/ ) {
print "$date\n$user\n$change\n$desc\n";
}
else {
print "no match\n";
}
输出:
DEC-12-2012
bugsbunny
5678
Modified Module
答案 3 :(得分:0)
$string = "* JAN-02-2001 bugsbunny 1234 Created Module";
$string = "* DEC-12-2012 bugsbunny 5678 Modified Module";
if($string =~ /^\*\s+(\w\w\w-\d\d-\d\d\d\d)\s+(\w+)\s+(\d+)\s+([^Created]|Modified)\s+(\w+)/){
print "$1\n$2\n$3\n$4\n";
}
else {
print "no match\n";
}