Papaya
Papaya

Reputation: 107

How to reverse a regular expression in Perl

I was trying to reverse a motif which is like a regular expression. An example of my motif : TA[TC]AA When I use the function (reverse) it reverses the [ into a ], so I obtained something like : AA]CT[AT and I want something like AA[CT]AT.

What can I do for it?

Thank you so much for your help!!

Upvotes: 3

Views: 1044

Answers (2)

amon
amon

Reputation: 57600

You cannot reverse all Perl regular expressions. But in this simple case where you only have literal characters or simple character classes, you could use an approach where you disassemble the regex atom by atom, then reverse the list of atoms. Here, an atom would be any regex thingy that matches independently, e.g. a literal character or a charclass.

sub reverse_pattern {
  my ($pattern) = @_;
  my @atoms;
  while (length $pattern) {
    # parse a literal (here, we just match letters)
    if ($pattern =~ s/^(\w)//) {
      push @atoms, $1;
    }
    # parse a charclass: \[ ... \]
    # the inside of a charclass is anything except "]" or "\": [^\]\\]+
    elsif ($pattern =~ s/^(\[[^\]\\]+\])//) {
      push @atoms, $1;
    }
    else {
      die "Unsupported pattern syntax: $pattern";
    }
  }
  return join '' => reverse @atoms;
}

use Test::More;
is reverse_pattern('TA[TC]AA'), 'AA[TC]AT';
done_testing;

Upvotes: 3

choroba
choroba

Reputation: 241858

If the square brackets are the only problem, use transliteration to switch them:

#! /usr/bin/perl
use warnings;
use strict;
use Syntax::Construct qw{ /r };

use Test::More tests => 1;

my $motif    = 'TA[TC]AA';
my $reversed = 'AA[CT]AT';

is reverse($motif =~ tr/[]/][/r), $reversed;

Or, in pre-5.14 where /r isn't available:

my $r = reverse $motif;
$r =~ tr/[]/][/;

Upvotes: 5

Related Questions