Perl Regex Regular Expression matches string except match string

Can anyone help me with this regex please? I need an expression that will match a string that does not contain the string "Created" at the end. This script is used to read the headers in some kind of source code.

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

When using the first definition of the string $, I need the match to fail because at the end it has the word "Created". When using the second definition of $ string, it must go through, and I need to pull out the date ($ 1), user ($ 2), change number ($ 3) and description ($ 4).

The above expression does not work. Any tips please?

+4
source share
4 answers

Close

 /^\*\s+(\w{3}-\d{2}-\d{4})\s+(\w+)\s+(\d+)\s+(?!.*Created)/ 

You need to allow any number of characters other than a newline to Created , therefore .* .

Otherwise, the regular expression will simply back up one character when matching \s+ , so the next text will be " Created" and then (?!Created) will match.

Look here ; notice how the match stops one space before Created .

+4
source

Another trick you can use to do this job is to use a group (?>...) that disables backtracking. Disabling backtracking means that any expression using + or * will eagerly eat whatever it finds and will never come back to try something else if the template doesn't work. This means that all spaces before "Created" are eaten, so part of the regular expression (?!Created) always occurs in the exact right place.

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

It also has an added bonus to make your regular expression much faster.

This approach does not work for all problems, because many regular expressions must be able to indent to fit correctly. But that will work just fine for this.

+1
source

Another option is to split and test the description for "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"; } 

Output:

 DEC-12-2012 bugsbunny 5678 Modified Module 
0
source
 $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"; } 
0
source

All Articles