Perl 5.8 RE for fixed string with an optional colon terminated prefix

R

RedGrittyBrick

I need to match fixed string FOO with an optional : terminated prefix

This doesn't work because the RE matches notFOO

for my $x (qw(FOO xxx:FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ /^[^:]*:?FOO$/) {
print "Matched $x\n";
} else {
print "- $x\n";
}
}

Actual output:

Matched FOO
Matched xxx:FOO
Matched yyy.FOO
- BAR
Matched notFOO
- FOOM

Desired output:

Matched FOO
Matched xxx:FOO
Matched yyy.FOO
- BAR
- notFOO
- FOOM

xxx and yyy are just examples of \w+ excluding ':'

I've glanced at perlretut but would appreciate a clue.
 
R

RedGrittyBrick

I need to match fixed string FOO with an optional : terminated prefix

This doesn't work because the RE matches notFOO

for my $x (qw(FOO xxx:FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ /^[^:]*:?FOO$/) {

if ($x =~ /^[^:]*:?\bFOO$/) {
print "Matched $x\n";
} else {
print "- $x\n";
}
}

I knew I'd end up feeling stupid :)
 
H

Helmut Richter

if ($x =~ /^[^:]*:?\bFOO$/) {

That will still independetly check for optional [^:]* and optional :
letting ,,,FOO pass. What you mean is probably /^([^:]+:)?\bFOO$/.
Here I assumed that the part before the colon is nonempty if the colon is
present.
 
R

RedGrittyBrick

if ($x =~ /^[^:]*:?\bFOO$/) {

That will still independetly check for optional [^:]* and optional :
letting ,,,FOO pass. What you mean is probably /^([^:]+:)?\bFOO$/.

Ah yes.
Here I assumed that the part before the colon is nonempty if the colon is
present.

Your assumption is correct.

Thanks
 
U

Uri Guttman

if ($x =~ /^[^:]*:?\bFOO$/) {

HR> That will still independetly check for optional [^:]* and optional
HR> : letting ,,,FOO pass. What you mean is probably
HR> /^([^:]+:)?\bFOO$/. Here I assumed that the part before the colon
HR> is nonempty if the colon is present.

i was going to suggest the grouping too. he says the whole prefix is
optional but he made the parts seperately optional instead. but now you
don't need the \b since if whole prefix is matched and it ends with :
and then sees FOO which means it always has a word boundary. also make
the group non-grabbing to speed it up unless he needs to grab the
prefix.

uri
 
S

sln

I need to match fixed string FOO with an optional : terminated prefix

This doesn't work because the RE matches notFOO

for my $x (qw(FOO xxx:FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ /^[^:]*:?FOO$/) {
^^^^^^^^
This can't be generalized to be put together without alternation.
^ and [^:]*:? need to be alternatives as a prefix to FOO
Because it makes you have to say [^:]*:? and the quantifiers
* ? make posibile any char not :* zero or more times then :?
zero or one time.

This makes it too particular in its need to find : and results
in everything else not : getting by and matching. Even if you used
[.:] it wouldn't work.

From your own description, you positively are looking for only
2 things to match:

1. FOO all by itself
2. FOO prefixed by anything plus : or .

Thats the way you have to write the regexp.
Lets also asume that 1 and 2 above can be surrounded by optional
whitespace:

1. FOO all by itself
/ ^ \s* FOO \s* $ /x
2. FOO prefixed by anything plus : or .
/ .+[.:] FOO \s* $ /xs

Join them together via factoring:

/ (?: ^\s* | .+[.:] ) FOO \s* $/xs
print "Matched $x\n";
} else {
print "- $x\n";
}
}

Matched () FOO
Matched (xxx:) xxx:FOO
Matched (yyy.) yyy.FOO
- BAR
- notFOO
- FOOM

-----------------------
use strict;
use warnings;

for my $x (qw(FOO xxx:FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ / ( ^\s* | .+[.:] ) FOO \s* $/xs) {
print "Matched ($1) $x\n";
} else {
print "- $x\n";
}
}
__END__

-sln
 
S

sln

I need to match fixed string FOO with an optional : terminated prefix

This doesn't work because the RE matches notFOO

for my $x (qw(FOO xxx:FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ /^[^:]*:?FOO$/) {
print "Matched $x\n";
} else {
print "- $x\n";
}
}

Another possiblity:

Avoid having to describe everything preceeding FOO.
And, if you don't care about captureing all before FOO,
this should speed up the search/matching if you have
alot to parse.

use strict;
use warnings;

for my $x (qw(FOO :FOO xxx:FOO .FOO yyy.FOO BAR notFOO FOOM)) {
if ($x =~ / (?: ^ | (?<=[:.]) ) \s* FOO \s* $ /x) {
print "Matched $x\n";
print "Matched ($1) $x\n";
} else {
print "- $x\n";
}
}
---------------

Matched FOO
Matched :FOO
Matched xxx:FOO
Matched .FOO
Matched yyy.FOO
- BAR
- notFOO
- FOOM
 
S

sln

if ($x =~ /^[^:]*:?\bFOO$/) {

That will still independetly check for optional [^:]* and optional :
letting ,,,FOO pass. What you mean is probably /^([^:]+:)?\bFOO$/.
Here I assumed that the part before the colon is nonempty if the colon is
present.


this - /^([^:]+:)?\bFOO$/

Indeed, grouping the the optional [^:]* and optional :
into a ()? took care of [^:]* letting ,,,FOO pass

However, by doing that, you don't let "prefix.FOO" pass.
This is why he had the :? independently optional so that

^[^:]*:?\bFOO$ would match 'prefix.FOO'

The \b protects the '.FOO' and the 'FOO' at the same time.
where [^:]*:? specifically matches 'prefix:FOO' and just so
happens : is compliant with \b and redundant.

Grouping changes the condition. Now \b won't find '.FOO'
because the search never consumes a '.'

This /^([^:]+:)?\bFOO$/ regexp at best is bloviated and redundant,
at worst will not match the conditions.

-sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top