Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re^2: multiple substitution

by naturalsciences (Beadle)
on Aug 25, 2012 at 10:08 UTC ( #989711=note: print w/ replies, xml ) Need Help??


in reply to Re: multiple substitution
in thread multiple substitution

Could you explain the code for a sec. Should those ! be /.

I can understand $string =~ s/(apples|oranges|bananas)/$replace{$1}/e would take the first match from string ($1). Then because the /e tag the second part in substitution would be value complement to the key ($1). What is the deal with the || (or?) statement. (I guess I'm mistaken with the ! elements) Would this (mine own )code work?
#!/usr/bin/perl -w use strict; use warnings; my @keys = qw(F29-2 F29-3 F29-4 F44-2 F53-2 F38-3 F12-2); my @vals = qw(F29B2 F29B3 F29B4 F44B2 F53B2 F38B3 F12B2); my %replace; @replace{@keys} = @vals; while (my $line = <>) { if($line =~ m/^\>/){my $name=$line;$name =~ s/(F29-2,F29-3,F29-4,F +44-2,F53-2,F38-3,F12-2)/$replace{$1}/;print $name;} elsif ($line!~m/^\>/){print $line;} }
Did not want to use some convoluted regexp patterns because they might be usable this time but not always. Want to learn the tehnique to do such list/hash substitutions as in original question.


Comment on Re^2: multiple substitution
Select or Download Code
Re^3: multiple substitution
by cheekuperl (Monk) on Aug 25, 2012 at 13:07 UTC
    Should those ! be / That ! is alright. Perl allows that.

    Could you explain the code for a sec.
    $replace{$1} || $1
    This part helps you replace the matched string with itself in case %replace does not have corresponding key. For example,

    Did not want to use some convoluted regexp
    Trust me, this is a simple regex. It can get a lot worse, if you delve deeper :)

    Want to learn the tehnique to do such list/hash substitutions as in original question
    As far as searching and replacing in strings is concerned, I guess regexes would be most helpful.
Re^3: multiple substitution
by Corion (Pope) on Aug 25, 2012 at 13:20 UTC
    If you are unfamiliar with s/// and s!!!, I already linked to the relevant documentation, perlop. Please read it. Regarding your own attempt, what happened when you tried it?
Re^3: multiple substitution
by AnomalousMonk (Abbot) on Aug 25, 2012 at 17:28 UTC
    Did not want to use some convoluted regexp patterns ... Want to learn the tehnique to do such list/hash substitutions ...

    A common approach to handling long search/replace string lists is to generate the search regex automatically from the keys of the search/replace hash. (Then you just have to worry about getting the hash right!)

    >perl -wMstrict -le "my @keys = qw(F29-2 F29-3 F29-4 F44-2 F53-2 F38-3 F12-2); my @vals = qw(F29B2 F29B3 F29B4 F44B2 F53B2 F38B3 F12B2); my %replace; @replace{@keys} = @vals; ;; my $rx_search = join q{ | }, map quotemeta, keys %replace; $rx_search = qr{ $rx_search }xms; print $rx_search; ;; my $s = 'F99-9 FF29-22 -F29-2- F29-2 F44-2 F12-2'; print qq{'$s'}; my $t = $s; $t =~ s{ ($rx_search) }{$replace{$1}}xmsg; print qq{'$t'}; ;; $t = $s; $t =~ s{ \b ($rx_search) \b }{$replace{$1}}xmsg; print qq{'$t'}; ;; $t = $s; $t =~ s{ (?<! \S) ($rx_search) (?! \S) }{$replace{$1}}xmsg; print qq{'$t'}; " (?^msx: F29\-4 | F53\-2 | F44\-2 | F29\-2 | F38\-3 | F29\-3 | F12\-2 ) 'F99-9 FF29-22 -F29-2- F29-2 F44-2 F12-2' 'F99-9 FF29B22 -F29B2- F29B2 F44B2 F12B2' 'F99-9 FF29-22 -F29B2- F29B2 F44B2 F12B2' 'F99-9 FF29-22 -F29-2- F29B2 F44B2 F12B2'

    Note that none of the conversion examples use the  /e switch, which will make conversion slightly faster. In all the conversion examples, F99-9 is never converted: it just doesn't appear in the conversion  @keys array.

    In the first conversion example, the F29-2 substring in FF29-22 and -F29-2- is converted even though it is embedded in another string: it appears in the conversion list.

    This is fixed for FF29-22 in the second example by using  \b boundary assertions to allow conversion only if a search string is neither preceded nor followed by a 'word' character ([A-Za-z0-9_]), but this still allows the substring in -F29-2- to be replaced because '-' is not a word character.

    This problem (if problem it is) is fixed in the third example by using different boundary assertions:  (?<! \S) and  (?! \S) allow a match (and replacement) only if the potential match substring is neither preceded nor followed by a non-whitespace character.

    $name =~ s/(F29-2,F29-3,F29-4,F44-2,F53-2,F38-3,F12-2)/$replace{$1}/;

    Note that | (pipe) and not , (comma) is the alternation metacharacter.

    Update: aaron_baugher, in a reply already posted, gave an example of the automatic regex generation technique discussed above, but the examples of using boundary conditions to refine a match may still be useful.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://989711]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (10)
As of 2015-07-02 04:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (27 votes), past polls