Pattern remembering problem

S

Steve Hémond

Hi people,

I am following a very good Perl tutorial and I have reached this exercise :

....
"Your current program should count lines of a file which contain a certain
string. Modify it so that it counts lines with double letters (or any other
double character). Modify it again so that these double letters appear also
in parentheses. For example your program would produce a line like this
among others:

023 Amp, James Wa(tt), Bob Transformer, etc. These pion(ee)rs conducted many

Try to get it so that all pairs of letters are in parentheses, not just the
first pair on each line."
....


Here is my Perl program :

#!/usr/bin/perl -w

$file = '/home/shemond/Perl/electricity.txt';
open (INFO, $file);
$a = 1;
while ($line = <INFO>)
{

if ($line =~ (\w)\1)
{
$line =~ s/(\w)\1/($1)/g;
print "$a $line";
$a++;
}
else
{
print " $line";
}
}


Here is what my programs outputs :
023 Amp, James Wa(t), Bob Transformer, etc. These pion(e)rs conducted many

As you can see, my program is able to match doubled-character (although I'm
not sure if it's a proof match).

The problem is it prints only one character, not both characters.

I surely misundertand Pattern Remembering using the \1 variable.

Can anyone explain what I am doing wrong? I need more explanations about
pattern remembering ...

Thanks a lot for your answers!

Steve
 
D

D Borland

Steve Hémond said:
Hi people,

I am following a very good Perl tutorial and I have reached this exercise :

...
"Your current program should count lines of a file which contain a certain
string. Modify it so that it counts lines with double letters (or any other
double character). Modify it again so that these double letters appear also
in parentheses. For example your program would produce a line like this
among others:

023 Amp, James Wa(tt), Bob Transformer, etc. These pion(ee)rs conducted many

Try to get it so that all pairs of letters are in parentheses, not just the
first pair on each line."
...


Here is my Perl program :

#!/usr/bin/perl -w

$file = '/home/shemond/Perl/electricity.txt';
open (INFO, $file);
$a = 1;
while ($line = <INFO>)
{

if ($line =~ (\w)\1)
{
$line =~ s/(\w)\1/($1)/g;

ok change to the above line to this

$line =~ s/(\w\1)/($1)/g;

the regular expression engine will remember by parentheses, so you had
(\w)\1 which means that $1 only holds the first occurence of the double
letter, you did it right in the if block, but you overwrote the data held in
$1 when you entered the substitution line.

Also check your perl docs on how to us the magic $_ as this is gonna save
you some typing :)

Dagmar
 
J

Jeff 'japhy' Pinyan

ok change to the above line to this

$line =~ s/(\w\1)/($1)/g;

Wrong. \1 isn't defined until AFTER the () is closed.

First, get rid of the if statement. It's totally unnecessary.

while ($line = <FILE>) {
$line =~ s/(\w)\1/($1$1)/g;
print $line;
}

That does all you need. Another way to write it would be

$line =~ s/((\w)\2)/($1)/g;

but I think that's more work than it's worth.
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi people,
Hi.

if ($line =~ (\w)\1)
{
$line =~ s/(\w)\1/($1)/g;
print "$a $line";
$a++;
}

For one thing, this can be simplified:

if ($line =~ s/(\w)\1/($1)/g)
{
print "$a $line";
$a++;
}

That way, you don't have to repeat the pattern. Mark Dominus has said
something like "If you write the same code twice, you've made a mistake",
and that's a good rule of thumb.

Here is what my programs outputs :
023 Amp, James Wa(t), Bob Transformer, etc. These pion(e)rs conducted
many

As you can see, my program is able to match doubled-character
(although I'm not sure if it's a proof match).

The problem is it prints only one character, not both characters.

I surely misundertand Pattern Remembering using the \1 variable.

Your pattern is /(\w)\1/. $1 is whatever is within the parentheses,
which is a single character. You can either do:

s/(\w)\1/($1$1)/
or
s/((\w)\2)/($1)/

whichever suits your fancy.

- --
Eric
$_ = reverse sort $ /. r , qw p ekca lre uJ reh
ts p , map $ _. $ " , qw e p h tona e and print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBP3ZGUWPeouIeTNHoEQJ6XwCg+1FA7IanxXeAtJ69k3khd1tjG14AoNeu
xihzPKgWGnn20pdqirq7H8PH
=HaZk
-----END PGP SIGNATURE-----
 
D

D Borland

if ($line =~ (\w)\1)
Wrong. \1 isn't defined until AFTER the () is closed.

First, get rid of the if statement. It's totally unnecessary.
Yeah dude, your right of course, bit sleeping being 3.30am, and i took a
break on here from some scripts i'm writing... well i'll use tha as an
excuse anyway :)

Dagmar
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

First, get rid of the if statement. It's totally unnecessary.

while ($line = <FILE>) {
$line =~ s/(\w)\1/($1$1)/g;
print $line;
}

That does all you need.

Except that the OP needs the line to be printed in a different format (with
a counter) if the substitution succeeded than if it failed.

- --
Eric
$_ = reverse sort $ /. r , qw p ekca lre uJ reh
ts p , map $ _. $ " , qw e p h tona e and print

-----BEGIN PGP SIGNATURE-----
Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

iQA/AwUBP3ZG6WPeouIeTNHoEQIkGwCdGxXC+1wflAvOZE4igQ1jK200chsAnisn
bpgha/SnQkJBwBMZ7yAHD/P4
=oGrh
-----END PGP SIGNATURE-----
 
S

Steve Hémond

Jeff said:
Wrong. \1 isn't defined until AFTER the () is closed.

First, get rid of the if statement. It's totally unnecessary.

while ($line = <FILE>) {
$line =~ s/(\w)\1/($1$1)/g;
print $line;
}

That does all you need. Another way to write it would be

$line =~ s/((\w)\2)/($1)/g;

but I think that's more work than it's worth.

I really need to keep the IF statement because as the exercice asks, I need
to print a line number in front of line which match the occurence.

Am I right?

Steve
 
M

Mina Naguib

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi people,

I am following a very good Perl tutorial and I have reached this exercise :

...
"Your current program should count lines of a file which contain a certain
string. Modify it so that it counts lines with double letters (or any other
double character). Modify it again so that these double letters appear also
in parentheses. For example your program would produce a line like this
among others:

023 Amp, James Wa(tt), Bob Transformer, etc. These pion(ee)rs conducted many

Try to get it so that all pairs of letters are in parentheses, not just the
first pair on each line."
...


Here is my Perl program :

#!/usr/bin/perl -w

$file = '/home/shemond/Perl/electricity.txt';
open (INFO, $file);
$a = 1;
while ($line = <INFO>)
{

if ($line =~ (\w)\1)
{
$line =~ s/(\w)\1/($1)/g;
print "$a $line";
$a++;
}
else
{
print " $line";
}
}


Here is what my programs outputs :
023 Amp, James Wa(t), Bob Transformer, etc. These pion(e)rs conducted many

As you can see, my program is able to match doubled-character (although I'm
not sure if it's a proof match).

The problem is it prints only one character, not both characters.

I surely misundertand Pattern Remembering using the \1 variable.

Can anyone explain what I am doing wrong? I need more explanations about
pattern remembering ...

Thanks a lot for your answers!

Hi Steve. It's good to see such enthusiasm (and people who actually try stuff out before posting).

In this line:
$line =~ s/(\w)\1/($1)/g;

It says (in English):
Find a word character, capture it in $1, followed by the same character
then
Replace both with an opening bracket, the matched character in $1, then a closing bracket

There are 2 (actually many) ways to fix this:

$line =~ s/(\w)\1/($1$1)/g;

Which repeats the matched character twice in the substitution.

Or the more-awkward (in my opinion) way:

$line =~ s/((\w)\2)/($1)/g;

Which captures BOTH letters in $1 as opposed to just the first one.

Best of luck.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQE/dlSPeS99pGMif6wRAhU2AJ9aPOkYBlD/ZKKloDlmVYH/Zn4uNACfR/Q1
e8qaTvx+IOvLleB0G1KGWng=
=vCu/
-----END PGP SIGNATURE-----
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top