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

Discussion in 'Perl Misc' started by joe rockhead, Oct 15, 2005.

  1. joe rockhead

    joe rockhead Guest

    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?
     
    joe rockhead, Oct 15, 2005
    #1
    1. Advertising

  2. joe rockhead <> wrote in news:Oc-
    :

    >
    > 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

    --
    A. Sinan Unur <>
    (reverse each component and remove .invalid for email address)

    comp.lang.perl.misc guidelines on the WWW:
    http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.html
     
    A. Sinan Unur, Oct 15, 2005
    #2
    1. Advertising

  3. joe rockhead

    Guest

    joe rockhead wrote:
    > 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.
     
    , Oct 15, 2005
    #3
  4. joe rockhead

    Guest

    wrote:
    > joe rockhead wrote:
    > > 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;
    > }
    >


    or maybe even...

    $string =~ s/(1|2|3)/$hash{$1}/g;
     
    , Oct 15, 2005
    #4
  5. joe rockhead wrote:
    >
    > 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
     
    RedGrittyBrick, Oct 15, 2005
    #5
  6. RedGrittyBrick wrote:
    > #!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.
     
    RedGrittyBrick, Oct 15, 2005
    #6
  7. joe rockhead

    joe rockhead Guest

    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?
     
    joe rockhead, Oct 15, 2005
    #7
  8. joe rockhead wrote:
    > 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.
     
    it_says_BALLS_on_your forehead, Oct 15, 2005
    #8
  9. joe rockhead

    joe rockhead Guest

    RedGrittyBrick wrote:
    > 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?
     
    joe rockhead, Oct 15, 2005
    #9
  10. joe rockhead

    Eric Bohlman Guest

    RedGrittyBrick <> wrote in news:dirde0$1fq$1
    @nwrdmz02.dmz.ncs.ea.ibs-infra.bt.com:

    > #!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.

    > s/$feature/$upgrade{$feature}/eg;
    > }
    > print;
    > }
     
    Eric Bohlman, Oct 16, 2005
    #10
  11. joe rockhead

    Dr.Ruud Guest

    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'.

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Oct 16, 2005
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. hiwa
    Replies:
    0
    Views:
    640
  2. Victor
    Replies:
    2
    Views:
    649
    Victor
    May 17, 2004
  3. ekzept
    Replies:
    0
    Views:
    375
    ekzept
    Aug 10, 2007
  4. John Gordon
    Replies:
    13
    Views:
    490
    Ian Kelly
    Dec 20, 2011
  5. Replies:
    3
    Views:
    175
    Brian McCauley
    Sep 12, 2005
Loading...

Share This Page