user87005
user87005

Reputation: 980

perl regex matching failed

I want to match two different string and output should come in $1 and $2, According to me in this example, if $a is 'xy abc', then $1 should be 'xy abc' and $2 should 'abc', but 'abc' part is coming in $3. Can you please help me to writing a regex in that $1 should have whole string and $2 should have second part. I am using perl 5.8.5.

my @data=('abc xy','xy abc');
foreach my $a ( @data) {
    print "\nPattern= $a\n";
    if($a=~/(abc (xy)|xy (abc))/) {
        print "\nMatch: \$1>$1< \$2>$2< \$3>$3<\n";
    }
}

Output:

perl test_reg.pl

Pattern= abc xy

Match: $1>abc xy< $2>xy< $3><

Pattern= xy abc

Match: $1>xy abc< $2>< $3>abc<

Upvotes: 5

Views: 1318

Answers (3)

Greg Bacon
Greg Bacon

Reputation: 139621

If you can live with allowing more capture variables than $1 and $2, then use the substrings from the branch of the alternative that matched.

for ('abc xy', 'xy abc') {
  print "[$_]:\n";

  if (/(abc (xy))|(xy (abc))/) {
    print "  - match: ", defined $1 ? "1: [$1], 2: [$2]\n"
                                    : "1: [$3], 2: [$4]\n";
  }
  else {
    print "  - no match\n";
  }
}

Output:

[abc xy]:
  - match: 1: [abc xy], 2: [xy]
[xy abc]:
  - match: 1: [xy abc], 2: [abc]

Upvotes: 0

Borodin
Borodin

Reputation: 126742

Because only one of captures $2 and $3 can be defined, you can write

foreach my $item ( @data) {

  print "\nPattern= $item\n";

  if ($item=~/(abc (xy)|xy (abc))/) {
    printf "Match: whole>%s< part>%s<\n", $1, $2 || $3;
  }
}

which gives the output

Pattern= abc xy
Match: whole>abc xy< part>xy<

Pattern= xy abc
Match: whole>xy abc< part>abc<

Upvotes: 1

Qtax
Qtax

Reputation: 33918

Can be done with:

(?|(abc (xy))|(xy (abc)))

Why even bother with capturing the whole thing? You can use $& for that.

my @data = ('abc xy', 'xy abc');
for(@data) {
    print "String: '$_'\n";

    if(/(?|abc (xy)|xy (abc))/) {
        print "Match: \$&='$&', \$1='$1'\n";
    }
}

Upvotes: 4

Related Questions