Home > Archive > PERL Miscellaneous > March 2004 > Regex match for one and only one occurrence of a pattern
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Regex match for one and only one occurrence of a pattern
|
|
| Steve Allgood 2004-03-28, 10:22 pm |
| I'm trying to match one and only one occurrence of a pattern in a string.
For example, for the pattern 'bc' I want a regex to match 'abcd' but not 'abcdabcd'.
I have tried /bc(?!(.*bc)+)/ but that doesn't work. It just matches the last 'bc'.
Any suggestions?
Thanks,
Steve
| |
| Tad McClellan 2004-03-29, 1:31 am |
| Steve Allgood <chiriones@yahoo.com> wrote:
> I'm trying to match one and only one occurrence of a pattern in a string.
>
> For example, for the pattern 'bc' I want a regex to match 'abcd' but not 'abcdabcd'.
>
> I have tried /bc(?!(.*bc)+)/ but that doesn't work. It just matches the last 'bc'.
>
> Any suggestions?
print "matched\n" if s/bc/bc/g == 1;
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Brian McCauley 2004-03-29, 7:34 am |
| Tad McClellan <tadmc@augustmail.com> writes:
> Steve Allgood <chiriones@yahoo.com> wrote:
>
>
> print "matched\n" if s/bc/bc/g == 1;
Nice, but using s/// to not modify a string makes me feel a little
uncomfortable.
print "matched\n" if (() = /bc/g) == 1;
Note: The above only works for regex with no captures.
Or..
# Assume pos() == 0 initially
print "matched\n" if /bc/g && ! /bc/g;
# Warning: maybe pos() != 0 now
Or rather more directly...
print "matched\n" if /bc/ && !/bc.*bc/;
Of course if you must do it in one regex:
print "matched\n" if /^(?!(.*bc){2}).*bc/;
However if you are compelled to use a single regex because you are
calling a function that takes a regex argument you may want to alter
that function to accept coderef arguments too.
--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\
| |
| Tad McClellan 2004-03-29, 9:45 am |
| Brian McCauley <nobull@mail.com> wrote:
> Tad McClellan <tadmc@augustmail.com> writes:
>
[color=darkred]
[color=darkred]
>
> Nice, but using s/// to not modify a string makes me feel a little
> uncomfortable.
>
> print "matched\n" if (() = /bc/g) == 1;
I had that one too, but I felt it had too much "startle factor" to post.
> Or..
>
> # Assume pos() == 0 initially
> print "matched\n" if /bc/g && ! /bc/g;
> # Warning: maybe pos() != 0 now
>
>
> Or rather more directly...
>
> print "matched\n" if /bc/ && !/bc.*bc/;
>
> Of course if you must do it in one regex:
>
> print "matched\n" if /^(?!(.*bc){2}).*bc/;
I gave The Way I did because the alternatives fell victim to:
it doesn't pass the 'just read it aloud' test
(some good advice that I was given here recently)
Now the pendulum swings the other way. :-)
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Richard Morse 2004-03-29, 3:36 pm |
| In article <e33c37bb.0403281853.2e6a0156@posting.google.com>,
chiriones@yahoo.com (Steve Allgood) wrote:
> I'm trying to match one and only one occurrence of a pattern in a string.
>
> For example, for the pattern 'bc' I want a regex to match 'abcd' but not
> 'abcdabcd'.
>
> I have tried /bc(?!(.*bc)+)/ but that doesn't work. It just matches the last
> 'bc'.
Well, you have the negative look-ahead, so maybe you need a negative
look-behind?
You'll have to play around with this a bit, as this is completely
untested...
print "matched" if m/(?<!bc.*)bc(?!.*bc)/;
HTH,
Ricky
| |
| Paul Lalli 2004-03-29, 4:34 pm |
| On Mon, 29 Mar 2004, Richard Morse wrote:
> In article <e33c37bb.0403281853.2e6a0156@posting.google.com>,
> chiriones@yahoo.com (Steve Allgood) wrote:
>
>
> Well, you have the negative look-ahead, so maybe you need a negative
> look-behind?
>
> You'll have to play around with this a bit, as this is completely
> untested...
>
> print "matched" if m/(?<!bc.*)bc(?!.*bc)/;
>
I think that'll cause a regexp error, as lookbehind assertions must be
fixed-width
Move the .* out of the assertion:
print "matched" if m/(?<!bc).*bc.*(?!bc)/;
The .* is allowable in the lookahead, of course. I just moved it out for
symmetry's sake.
Paul Lalli
| |
| Steven Kuo 2004-03-29, 4:34 pm |
| On 28 Mar 2004, Steve Allgood wrote:
> I'm trying to match one and only one occurrence of a pattern in a
> string.
>
> For example, for the pattern 'bc' I want a regex to match 'abcd'
> but not 'abcdabcd'.
>
> I have tried /bc(?!(.*bc)+)/ but that doesn't work. It just
> matches the last 'bc'.
>
> Any suggestions?
>
> Thanks,
> Steve
One way:
if ( @{[ m/bc/g ]} == 1 ) {
# matched just once
}
--
Hope this helps,
Steven
|
|
|
|
|