match 1/2/3, replace with a/b/c

J

joe rockhead

I'm not sure what the name of the concept is, but here goes.

I want to find 1 or 2 or 3 and replace it with a or b or c.

if it finds 1, replace it with a.
2 => b
and 3 => c.




I understand that
s/1|2|3/x/
replaces 1,2 or 3 with x.

anyway here's what I'm doing about it:


use IO::All;
my @list = io('list.txt')->slurp;
my $message < io 'passage.txt';

for (@list){
my ($preFilter, $postFilter) = split /=/, $_;
$message =~ s/$preFilter/$postFilter/g;
}



Where list.txt:
486DX=P4
640KB=2GB
50MB HDD=400GB HDD
1.44MB FDD=Flash Media Reader
6X CD-ROM=6X DL DVD

and message.txt:
My blasing fast 486DX with 640KB of RAM
50MB HDD 1.44MB FDD
6X CD-ROM



so I'm thinking:
s/1|2|3/a|b|c/
but that dosen't work.

what I'm I looking for?
what's it called?
 
A

A. Sinan Unur

I'm not sure what the name of the concept is, but here goes.

I want to find 1 or 2 or 3 and replace it with a or b or c.

if it finds 1, replace it with a.
2 => b
and 3 => c.

#!/usr/bin/perl

use strict;
use warnings;

my $s = '123';
$s =~ tr/123/abc/;
print "$s\n";

__END__
I understand that
s/1|2|3/x/
replaces 1,2 or 3 with x.

anyway here's what I'm doing about it:


use IO::All;
my @list = io('list.txt')->slurp;
my $message < io 'passage.txt';

for (@list){
my ($preFilter, $postFilter) = split /=/, $_;
$message =~ s/$preFilter/$postFilter/g;
}

Please post code others can run without jumping through a lot of hoops.
Please read the posting guidelines to learn how you can help yourself,
and help others help you.

Where list.txt:
486DX=P4
640KB=2GB
50MB HDD=400GB HDD
1.44MB FDD=Flash Media Reader
6X CD-ROM=6X DL DVD

and message.txt:
My blasing fast 486DX with 640KB of RAM
50MB HDD 1.44MB FDD
6X CD-ROM

What does this have to do with the requirement you set out in the
beginning? You have not specified how you get from the input to the
output.

The following would produce the output you showed above:

#!/usr/bin/perl

use strict;
use warnings;

my %messages = (
cpu => 'My blasing fast %s ',
ram => "with %s of RAM\n",
hdd => "%s ",
fdd => "%s\n",
cdr => "%s\n",
);

my @features = qw( cpu ram hdd fdd cdr );

for my $feature (@features) {
my $info = <DATA>;
last unless $info =~ /^(.+)=.+$/;
printf($messages{$feature}, $1);
}

__DATA__
486DX=P4
640KB=2GB
50MB HDD=400GB HDD
1.44MB FDD=Flash Media Reader
6X CD-ROM=6X DL DVD
so I'm thinking:
s/1|2|3/a|b|c/
but that dosen't work.

what I'm I looking for?
what's it called?

No idea. You'll have to describe it better.

Sinan
 
S

simon.chao

joe said:
I'm not sure what the name of the concept is, but here goes.

I want to find 1 or 2 or 3 and replace it with a or b or c.

if it finds 1, replace it with a.
2 => b
and 3 => c.
so I'm thinking:
s/1|2|3/a|b|c/
but that dosen't work.

what I'm I looking for?
what's it called?

first, you want to create a hash to associate each number to its
corresponding letter.

# come up with a better name than i have, obviously
my %hash = (
1 => 'a',
2 => 'b',
3 => 'c',
);

# now for your string, assuming you already have it defined
while ( my ($key, $value) = each %hash ) {
$string =~ s/$key/$value/g;
}

....that should do it i think. i didn't run this code, so there may be a
stupid mistake i'm making, but that's the concept.
 
S

simon.chao

first, you want to create a hash to associate each number to its
corresponding letter.

# come up with a better name than i have, obviously
my %hash = (
1 => 'a',
2 => 'b',
3 => 'c',
);

# now for your string, assuming you already have it defined
while ( my ($key, $value) = each %hash ) {
$string =~ s/$key/$value/g;
}

or maybe even...

$string =~ s/(1|2|3)/$hash{$1}/g;
 
R

RedGrittyBrick

joe said:
I'm not sure what the name of the concept is, but here goes.

Forgive me, but I think your concept is a muddled one.

I want to find 1 or 2 or 3 and replace it with a or b or c.

No you don't, that would mean "1" could be replaced by "c", say.
if it finds 1, replace it with a.
2 => b
and 3 => c.

The above is clearer, you want three separate and distinct substitutions.

s/1/a/; s/2/b/; s/3/c/;
I understand that
s/1|2|3/x/
replaces 1,2 or 3 with x.

anyway here's what I'm doing about it:


use IO::All;
my @list = io('list.txt')->slurp;
my $message < io 'passage.txt';

I doubt that compiles!

To read files I'd use
open my $message, '<', 'passage.txt'
or die "Unable to open passage.txt: $!";
while (<$message>) {
# do stuff
}
close $message or die;
for (@list){
my ($preFilter, $postFilter) = split /=/, $_;
$message =~ s/$preFilter/$postFilter/g;
}

Did you actually try it? What errors did you see?

Where list.txt:
486DX=P4
640KB=2GB
50MB HDD=400GB HDD
1.44MB FDD=Flash Media Reader
6X CD-ROM=6X DL DVD

and message.txt:
My blasing fast 486DX with 640KB of RAM
50MB HDD 1.44MB FDD
6X CD-ROM
#!perl
use strict;
use warnings;

my %patterns = (
'486DX' => 'P4',
'640KB' => '2GB',
'50MB HDD' => '400GB HDD',
'1.44MB FDD' => 'Flash Media Reader',
'6X CD-ROM' => '6X DL DVD'
);

while (<DATA>) {
foreach my $key (keys %patterns) {
s/$key/$patterns{$key}/eg;
}
print;
}
__DATA__
My blasing fast 486DX with 640KB of RAM
50MB HDD 1.44MB FDD
6X CD-ROM


Output:
My blasing fast P4 with 2GB of RAM
400GB HDD Flash Media Reader
6X DL DVD
 
R

RedGrittyBrick

RedGrittyBrick said:
#!perl
use strict;
use warnings;

my %patterns = (
'486DX' => 'P4',
'640KB' => '2GB',
'50MB HDD' => '400GB HDD',
'1.44MB FDD' => 'Flash Media Reader',
'6X CD-ROM' => '6X DL DVD'
);

while (<DATA>) {
foreach my $key (keys %patterns) {
s/$key/$patterns{$key}/eg;
}
print;
}

You know, its often just after hitting the send button that I think of a
much better way of naming variables or some other such thing:

#!perl
use strict;
use warnings;

my %upgrade = (
'486DX' => 'P4',
'640KB' => '2GB',
'50MB HDD' => '400GB HDD',
'1.44MB FDD' => 'Flash Media Reader',
'6X CD-ROM' => '6X DL DVD'
);

while (<DATA>) {
foreach my $feature (keys %upgrade) {
s/$feature/$upgrade{$feature}/eg;
}
print;
}


Ho hum.
 
J

joe rockhead

I don't know who to answer back to.
so, how about this.
I'm probably delusional, but I thought perhaps I may have seen something like this.

in a s///, you can use the | to find item1 or item2 or item3 and replace it with something.

so, is that a reges where I can s/// look for item1 replace it with something1
item2 with something2
and item 3 with something3 at the same time?
in one line of regex?

The code I put up before worked and did the job, but I just thought I may have seen a substitution that did it in
one line.

the hash that one of you put up works also.
and yes, I do own the orielly regex book and I did read it.
i just don't know if what i'm looking for exists and if it does what's it called?
 
I

it_says_BALLS_on_your forehead

joe said:
I don't know who to answer back to.
so, how about this.
I'm probably delusional, but I thought perhaps I may have seen something like this.

in a s///, you can use the | to find item1 or item2 or item3 and replace it with something.

so, is that a reges where I can s/// look for item1 replace it with something1
item2 with something2
and item 3 with something3 at the same time?
in one line of regex?

The code I put up before worked and did the job, but I just thought I may have seen a substitution that did it in
one line.

the hash that one of you put up works also.
and yes, I do own the orielly regex book and I did read it.
i just don't know if what i'm looking for exists and if it does what's it called?

i believe you are referring to backreferences (e.g. $1, $2, etc...).
These, when used in conjunction with a hash, will give you what you
want. see the post that uses the $1 above.
 
J

joe rockhead

RedGrittyBrick said:
joe rockhead wrote: ....

The above is clearer, you want three separate and distinct substitutions.


s/1/a/; s/2/b/; s/3/c/;

ah, yes.
perhaps this one.
can this be done in one step?
and what would it be called?
 
E

Eric Bohlman

#!perl
use strict;
use warnings;

my %upgrade = (
'486DX' => 'P4',
'640KB' => '2GB',
'50MB HDD' => '400GB HDD',
'1.44MB FDD' => 'Flash Media Reader',
'6X CD-ROM' => '6X DL DVD'
);

while (<DATA>) {
foreach my $feature (keys %upgrade) {

While it doesn't matter with the particular example data you used, in
general you should use

foreach my $feature (reverse sort keys %upgrade) {

so that if one or more feature names is a substring of another one, the
longest one will be matched.
 
D

Dr.Ruud

Eric Bohlman:
While it doesn't matter with the particular example data you
used, in general you should use

foreach my $feature (reverse sort keys %upgrade) {

so that if one or more feature names is a substring of another
one, the longest one will be matched.

For that you need to use the length, because a substring can also be
anywhere inside that other one.

Also beware of loops, like when replacements contain later searches.
Should not be a problem with 's/$feature/$upgrade{$feature}/eg'.
 

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,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top