24

I have to remove the string between two delimiters, i.e From "123XabcX321" I want "123321". For a simple case, I'm fine with:

$_=<>; s/X(.*)X//; print; 

But if there's ambiguity in the input like "123XabcXasdfjXasdX321", it matches the first X with the last X and I get "123321" but I want "123asdfj321". Is there a way to specify an "eager" match that matches with the first valid possible delimiter and not the last?

2 Answers 2

48

It's normally called "ungreedy", you put a ? after the quantifier: s/X(.*?)X//;

Sign up to request clarification or add additional context in comments.

7 Comments

and in the example given, /g would be needed to substitute more than once.
I think "non-greedy" is the more common term. At any rate, the default is greedy matching, and you want the opposite.
Note that in Gnu grep you'll need to use --perl-regexp (-P) for the lazy operator (or use the approach below). reference
Be aware of this: "XaXbXY" =~ /X(.*?)XY/ => aXb
@ikegami: Aware of what, it working exactly as it's supposed to?
|
8

Avoid the non-greedy modifier as anything but a performance hint if you can. Using it can lead to "unexpected" results because adding ? doesn't actually prevent .* from matching anything. For example,

$ perl -le'print for "XaXbXY" =~ /X(.*?)XY/;' aXb 

To avoid matching X, you can use the following:

s/X[^X]*X//g; 

If X is really something larger than one character, you can use the following:

s/X(?:(?!X).)*X//g; 

8 Comments

interesting... I'll try that. In my case, the X is more than one char. I'll have to decipher ?:(?!X) tho
@GClaramunt, (?: ) in regex patterns are like ( ) in Perl. In this case, it indicates that * affects (?!X). instead of just .. ( ) is frequently misused for this purpose.
@GClaramunt, (?! ) checks that what follows doesn't match the contained pattern.
Why do you prefer that?
@JohnS, Why don't I use (...).*?x(...) to prevent .* from matching x? Because it doesn't. Non-greediness provides a performance hint; it's not for preventing .* from matching. Using non-greediness as anything other than a performance hint is a fragile hack.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.