Perl Regex正则表达式匹配字符串,不匹配字符串

时间:2013-02-05 07:56:31

标签: regex perl pattern-matching

任何人都可以帮我解决这个正则表达式吗?我需要一个表达式,它将匹配最后不包含“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)。

上面的表达不起作用。有什么建议吗?

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";
}