http://www.perlmonks.org?node_id=263086

peppiv has asked for the wisdom of the Perl Monks concerning the following question:

Thanks for reading this. I'm having difficulty with a simple substitution that I want to occur only once. I've RTFM'd (Cookbook) but can't find the exact solution.

Let's see what silly things I've done.(The following code is stripped down for time/space convenience)

#!/usr/bin/perl -Tw use strict; $result = "43 P"; #comes from somewhere else in the program interpret_clock($result); sub interpret_clock { $_[0] =~ s/43 F/Tunnel 1\/2 Hr FT/o; $_[0] =~ s/43 P/Tunnel 1\/2 Hr PT/o; $_[0] =~ s/45 F/Tunnel No Lunch FT/o; $_[0] =~ s/45 P/Tunnel No Lunch PT/o; $_[0] =~ s/F/Full Time No Clock/o; $_[0] =~ s/O/On Call No Clock/o; $_[0] =~ s/P/Part Time No Clock/o; $_[0] =~ s/T/Temporary No Clock/o; } print $result;
I'd like it to print 'Tunnel 1/2 HR PT'. But what I get is 'Part Time No Clockunnel 1/2 HR PPart Time No Clock'. The substitutions for the single letters matches also. I'd only want them to match exactly on single letter values. I've tried using the match exact {1} but I couldn't get it to work.

Any ideas? Any direction someone could point me to?

peppiv

Replies are listed 'Best First'.
Re: Regex Substitution in sub
by Ovid (Cardinal) on Jun 04, 2003 at 18:12 UTC

    If your codes are that exact, do a hash lookup instead:

    sub interpret_clock { my %codes = ( '43 F' => 'Tunnel 1/2 Hr FT', '43 P' => 'Tunnel 1/2 Hr PT', '45 F' => 'Tunnel No Lunch FT', '45 P' => 'Tunnel No Lunch PT', 'F' => 'Full Time No Clock', 'O' => 'On Call No Clock', 'P' => 'Part Time No Clock', 'T' => 'Temporary No Clock', ); my $code = shift; unless (exists $codes{$code} ) { die "Unknown code: ($code)"; } return $codes{$code}; }

    You're much less likely to be in error with that.

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

      sub interpret_clock { my %codes = (

      It is probably a good idea to build the hash outside the sub, to avoid building it each time the sub is called.

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        Oops. You're right. Some days it doesn't pay to chew through the straps and log on.

        Cheers,
        Ovid

        New address of my CGI Course.
        Silence is Evil (feel free to copy and distribute widely - note copyright text)

Re: Regex Substitution in sub
by dws (Chancellor) on Jun 04, 2003 at 18:16 UTC
    I'd like it to print 'Tunnel 1/2 HR PT'. But what I get is 'Part Time No Clockunnel 1/2 HR PPart Time No Clock'.

    If your intent is to do no more than one substitution, then you need program logic to return after a substitution has been made. Something like

    $_[0] =~ s/foo/bar/ && return;
    might be what you're looking for.

    By the way, the /o isn't helping you in the slightest.

Re: Regex Substitution in sub
by thelenm (Vicar) on Jun 04, 2003 at 18:18 UTC
    If you only want to look up exact matches, you may want to stick the lookups in a hash rather than using substitutions in a subroutine (you might use your subroutine to access the hash instead). Maybe something like this?
    my %interpret = ( '43 F' => 'Tunnel 1/2 Hr FT', '43 P' => 'Tunnel 1/2 Hr PT', '45 F' => 'Tunnel No Lunch FT', '45 P' => 'Tunnel No Lunch PT', 'F' => 'Full Time No Clock', 'O' => 'On Call No Clock', 'P' => 'Part Time No Clock', 'T' => 'Temporary No Clock', ); my $result = "43 P"; # comes from somewhere else my $interpretation = $interpret{$result}; print $interpretation;

    -- Mike

    --
    just,my${.02}

      Thank you all. The && return does work. However, I think I will work with one of the hash solutions. I believe this would be best for this application.

      SUPA THANX

      peppiv

Re: Regex Substitution in sub
by artist (Parson) on Jun 04, 2003 at 18:16 UTC
    You can use hash here. It should have key-value pairs.
    Example:
    $interpret = { "45 F" => "Tunnel No Lunch FT", "F" => "Full Time No Clock" }; my $result = '45 F'; $result = $interpret->{$result}; print $result;
    artist
Re: Regex Substitution in sub
by pzbagel (Chaplain) on Jun 04, 2003 at 18:16 UTC

    The regex should say what you want to match, you don't do that so after the /P/ gets substituted the T fires on 'T'unnel. instead of the T after the P. Try:

    $_[0] =~ s/43 F/Tunnel 1\/2 Hr FT/o; $_[0] =~ s/43 P/Tunnel 1\/2 Hr PT/o; $_[0] =~ s/45 F/Tunnel No Lunch FT/o; $_[0] =~ s/45 P/Tunnel No Lunch PT/o; $_[0] =~ s/F(.$)/Full Time No Clock $1/o; $_[0] =~ s/O(.$)/On Call No Clock $1/o; $_[0] =~ s/P(.$)/Part Time No Clock $1/o; $_[0] =~ s/T$/Temporary No Clock/o;

    I don't know whether O is the first or second of the two character code you are substituting, I guessed it was the first char. Anyhow, it you tell it to substitute T at the end of the string, you get what you want.

    Hope this gets you closer to your goal.

Re: Regex Substitution in sub
by Aristotle (Chancellor) on Jun 04, 2003 at 23:31 UTC
    Just wanted to note that you shouldn't use /o. it does nothing in the examples you showed, so I suspect you don't know what exactly its effects are; in that case it can get you in big trouble. If you are using it because you read that it is about efficiency, read up about the qr// "operator" whose introduction in Perl 5.005 (almost) obsoleted /o.

    Makeshifts last the longest.

      I read today in everyone's favourite module:

      $toencode =~ s{&}{&amp;}gso; $toencode =~ s{<}{&lt;}gso; $toencode =~ s{>}{&gt;}gso; $toencode =~ s{"}{&quot;}gso; my $latin = uc $self->{'.charset'} eq 'ISO-8859-1' || uc $self->{'.charset'} eq 'WINDOWS-1252'; if ($latin) { # bug in some browsers $toencode =~ s{'}{&#39;}gso; $toencode =~ s{\x8b}{&#8249;}gso; $toencode =~ s{\x9b}{&#8250;}gso; if (defined $newlinestoo && $newlinestoo) { $toencode =~ s{\012}{&#10;}gso; $toencode =~ s{\015}{&#13;}gso; } } return $toencode;
      This is the heavy strictless module that everyone still recommends. /o? /s? WHY?!

      Can we please stop using and recommending CGI.pm now? Please?

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        Quoting myself from Re^3: Handy dandy CPAN pollution:
        I've poured over CGI myself. Basically, that module is a horrible mess. That's ok for someone who wants to use it, as it's not only one of the few messes that work, but one of the even fewer than work well in practice.
        I don't really like the module, but we need a good replacement. I was switching to CGI::Simple for a while (as I wrote there), but have now actually found CGI's HTML generation useful in combination with Template Toolkit, so I'm reluctantly back to it. We need a full replacement for all of the functionality of that mess before we can stop recommending it.. :-/

        Makeshifts last the longest.

Re: Regex Substitution in sub
by peppiv (Curate) on Jun 04, 2003 at 18:04 UTC
    OK. Sorry. It should read my $result

    my mistake.

    peppiv