How do I write this regex?

S

spydox

This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

Z! B! C! A! A! C! B! A! BE

I tried ?= but I don't see a way to make that work. I thought

s/(Z)(A|B|C)+/$1! $2/g;

might have a chance but it produced

'Z! BE'

I'm not sure I can explain that result.

If your suggestion involves a loop please dont make it, I know plenty
of ways to do that.

Thank-You
 
P

Paul Lalli

This is NOT homework!

My, my. Mighty defensive, aren't we?
I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! .

Try better English. An object for your transitive verb "preceed" would
be nice, for example.
So in this example I want the regex to produce:

Z! B! C! A! A! C! B! A! BE

I tried ?= but I don't see a way to make that work. I thought

s/(Z)(A|B|C)+/$1! $2/g;

might have a chance but it produced

'Z! BE'
I'm not sure I can explain that result.

Because your last parenthesized group has a + modifer. So when all is
said and done, $2 contains the *last* A, B, or C that it found. And
you replaced everything matched with $1, a !, and $2.
If your suggestion involves a loop please dont make it, I know plenty
of ways to do that.

Wait. You're imposing a requirement that you can't use a *loop*? And
you're claiming this isn't homework?

Please give me some real-life example of a situation in which a LOOP is
forbidden.

Paul Lalli
 
T

Todd W

This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

Z! B! C! A! A! C! B! A! BE

<snip OP's code>

This may work for you:

$ cat lbstrrep.pl
use warnings;
use strict;

my $sequence = 'ZBCAACBABE';

$sequence =~ s|Z([ABC]+)|'Z! ' . join('! ', split(//, $1))|eg;

print( $sequence, "\n" );

$ perl lbstrrep.pl
Z! B! C! A! A! C! B! A! BE

The /e modifier evaluates the replacement side of the regex as perl code and
uses the result as the replacement string.

Enjoy,

trwww
 
J

John W. Krahn

This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

Z! B! C! A! A! C! B! A! BE

I tried ?= but I don't see a way to make that work. I thought

s/(Z)(A|B|C)+/$1! $2/g;

might have a chance but it produced

'Z! BE'

I'm not sure I can explain that result.

If your suggestion involves a loop please dont make it, I know plenty
of ways to do that.

$ perl -le'
$_ = q/ZBCAACBABE/;
print;
s{(?<=Z)([ABC]+)}{(my$x=$1)=~s<(?=.)><! >g;$x}eg;
print;
'
ZBCAACBABE
Z! B! C! A! A! C! B! A! BE



John
 
E

Eric Bohlman

Wait. You're imposing a requirement that you can't use a *loop*? And
you're claiming this isn't homework?

Please give me some real-life example of a situation in which a LOOP is
forbidden.

I can: if the regex needs to be read in as data.
 
S

spydox

Paul - turn down the flames, I don't like doing other's homework here
and I wouldn't ask anyone else to do mine, that's all. No drama.. I'm
just stumped is all.
 
S

spydox

I'm not sure I can explain that result.
Because your last parenthesized group has a + modifer. So when all is
said and done, $2 contains the *last* A, B, or C that it found. And
you replaced everything matched with $1, a !, and $2.

Good explaination thanks! I sort of thought that the /g modifier would
interact differently with the + though. I was obviously wrong!

Spydox
 
S

spydox

I forbid it myself - as I said I know I can "loop" and solve this but I
prefer a regex over a loop *almost* everytime. 99% of the time I can
come up with a regex to solve anything that comes along, but this one
has me stumped!

Thanks everyone for the suggestions I'm trying them now. Particularly
your ideas John- that's sort of a intimidating regex but it sure seemed
to work! I'll have to cipher on that one a bit to comprehend it all

:)

Spydox
 
A

Anno Siegel

This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

That's not a regex you want, it's a substitution operation. There's
a difference.
Z! B! C! A! A! C! B! A! BE

Here is one way to do it:

s{Z([ABC]+)} {'Z' . join '', map "! $_", split //, $1}e;

or, same principle but using a nested substitution:

s{Z([ABC]+)} { my $x = $1; $x =~ s/(.)/! $1/g; "Z$x" }e;

Anno
 
J

John W. Krahn

Anno said:
This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

That's not a regex you want, it's a substitution operation. There's
a difference.
Z! B! C! A! A! C! B! A! BE

Here is one way to do it:

s{Z([ABC]+)} {'Z' . join '', map "! $_", split //, $1}e;

Or more simply:

s{(Z[ABC]+)} {join '! ', split //, $1}e;



John
 
A

Anno Siegel

John W. Krahn said:
Anno said:
This is NOT homework!

I want to comment out certain lines which immediately follow (as a
group) another line. I created a simple example:

$_ = 'ZBCAACBABE';

In English, for any group of A,B,or C's in any order, which follow a Z,
I want to preceed with ! . So in this example I want the regex to
produce:

That's not a regex you want, it's a substitution operation. There's
a difference.
Z! B! C! A! A! C! B! A! BE

Here is one way to do it:

s{Z([ABC]+)} {'Z' . join '', map "! $_", split //, $1}e;

Or more simply:

s{(Z[ABC]+)} {join '! ', split //, $1}e;

Oh... good. I thought of join, but dismissed it (too quickly) because
it doesn't prefix the first character. Very clever to exploit that
behavior.

Anno
 
S

spydox

Here is one way to do it:

s{Z([ABC]+)} {'Z' . join '', map "! $_", split //, $1}e;

Or more simply:

s{(Z[ABC]+)} {join '! ', split //, $1}e;

Oh... good. I thought of join, but dismissed it (too quickly) because
it doesn't prefix the first character. Very clever to exploit that
behavior.

Anno

I as well- I'm very impressed by this result. Thanks again John, nice
work.

I had a reply in email from Xicheng that suggested:

perl -le '$_ = "ZBCAACBABE";s/(.)(?=[ABC])/$1! /g;print'
==you get==
Z! B! C! A! A! C! B! A! BE

which I thought was REALLY SLICK.. However, I needed it to check for
"Z", not (.), so I replaced it with:

perl -le '$_ = "ZBCAACBABE";s/(Z))(?=[ABC])/$1! /g;print'
(which BROKE IT for some reason):
Z! BCAACBABE

Anyhow- I'm not futzing around with s/(.)(?=[ABC])/$1! /g trying to get
it to work correctly. I think Xicheng is onto something! I had
previously tried ?=(ABC) but not the character class.

Have a good weekend, thanks everyone for chiming in. I will comment
that "context-switching ops", that is using s/// to change everything
between A and B seems like a difficult thing to do. Maybe s/// isn't
the best tool for that...

Have a good weekend!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top