问题
I've a string "ajjjjjjjjjaab"
I want a pattern which will match the last "ab"
and not the whole string or even "aab"
.
/a.*?b/ # returns two groups
or
/a.??b/ # matches last aab
Neither works.
回答1:
A simple way around your problem is to match:
.*(a.*b)
With the first .*
being greedy, it matches as much as it can. Then you get a captured group with the match you really need, ($1
). Note that this assumes you're matching the last occurrence of the pattern. You may want .*(a.*?b)
if you have multiple b
s near the end of the string, and you want the first one after the last a
.
回答2:
One of:
/a[^a]*b/
/a[^ab]*b/
If a
and b
are actually more complex patterns, one can use the following:
/a(?:(?!a).)*b/s
/a(?:(?!a|b).)*b/s
If a
and b
represent long/complex patterns, one can avoid repeating them using variables like in any other code.
my $re1 = qr/a/;
my $re2 = qr/b/;
/$re1(?:(?!$re1|$re2).)*$re2/s
One can also use subpatterns.
/
(?&A) (?:(?!(?&A)|(?&B)).)* (?&B)
(?(DEFINE)
(?<A> a )
(?<B> b )
)
/xs
回答3:
The pattern matching in Perl is Left Most, Longest* by default. Using ??
, *?
, or +?
will change that portion to Left Most, Shortest, but Left Most still takes precedence.
There is a way to get Perl to match Right Most, which might get you your desired effect, but it will also confuse the hell out of the next person to read your code, so use it with care.
The basic idea is to reverse everything related to the pattern match, so right becomes left.
my $subject = 'ajjjjjjjjjaab';
my $rev_sub = reverse $subject; # reverse the string being matched.
my $result;
if ($rev_sub =~ /(b.*?a)/) { # reverse the pattern to match.
$result = reverse $1; # reverse the results of the match.
}
print $result;
The solutions provided by ikegami and Kobi both find similar results for your example. Depending on your real patterns and strings you might find very different performance for each method. Always Benchmark based off your real needs.
*Longest only for the immediate token being matched, excluding alternations which are tried in order left to right, etc.
回答4:
Ok, but then use just /ab/
for matching and you go it. Or /a{1}b/
. Or?
来源:https://stackoverflow.com/questions/5401571/how-can-i-match-the-shortest-possible-sequence-of-characters-that-satisfy-my-reg