mafu
mafu

Reputation: 32650

Regex: optional group

I want to split a string like this:

abc//def//ghi

into a part before and after the first occurrence of //:

a: abc
b: //def//ghi

I'm currently using this regex:

(?<a>.*?)(?<b>//.*)

Which works fine so far.

However, sometimes the // is missing in the source string and obviously the regex fails to match. How is it possible to make the second group optional?

An input like abc should be matched to:

a: abc
b: (empty)

I tried (?<a>.*?)(?<b>//.*)? but that left me with lots of NULL results in Expresso so I guess it's the wrong idea.

Upvotes: 4

Views: 8948

Answers (3)

gnud
gnud

Reputation: 78528

Why use group matching at all? Why not just split by "//", either as a regex or a plain string?

use strict;

my $str = 'abc//def//ghi';
my $short = 'abc';

print "The first:\n";
my @groups = split(/\/\//, $str, 2);
foreach my $val (@groups) {
print "$val\n";
}

print "The second:\n";
@groups = split(/\/\//, $short, 2);
foreach my $val (@groups) {
print "$val\n";
}

gives

The first:
abc
def//ghi
The second:
abc

[EDIT: Fixed to return max 2 groups]

Upvotes: -1

kjfletch
kjfletch

Reputation: 5494

A proof of Stevo3000's answer (Python):

import re

test_strings = ['abc//def//ghi', 'abc//def', 'abc']

regex = re.compile("(?P<a>.*?)(?P<b>//.*)?$")

for ts in test_strings:
    match = regex.match(ts)
    print 'a:', match.group('a'), 'b:', match.group('b')

a: abc b: //def//ghi
a: abc b: //def
a: abc b: None

Upvotes: 0

stevehipwell
stevehipwell

Reputation: 57488

Try a ^ at the begining of your expression to match the begining of the string and a $ at the end to match the end of the string (this will make the ungreedy match work).

^(?<a>.*?)(?<b>//.*)?$

Upvotes: 8

Related Questions