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

I would like to reverse a string, and then un-reverse it so that another string can act on it (for substitution). Have searched the manuals with no luck. If I dont reverse it, but simply do this, it works:
#!/usr/bin/perl print "Content-type: text/html\n\n"; ......This Works................... $comment = "My lawyer is named will"; for ($new_comment = $comment) { s/lawyer/Banker/eig; s/will/Barney/eig; s/is/Was/eig; } print $new_comment;
But when I try to reverse the string or array, the results dont work on the first string, even if I call in inside a sub.....
.......Why Doesnt This Work ? ................ $comment = "My lawyer is named will"; for ($new = $comment) { $comment = &doit($comment); } sub doit{ $go = ";gie/moT/lliw/s ;gie/reknaB/reywal/s ;gie/yenraB/derf/s"; $com = join("", reverse split(//, $go)); return $com; } print $new;
Yes, it is stupid to want to do this, but I need to. Could anyone please tell me how I might accomplish this. Thanks.

Edit kudra, 2002-04-15 Changed title

Replies are listed 'Best First'.
Re: newkid confused
by swiftone (Curate) on Apr 05, 2002 at 21:46 UTC
    Well, let's see what you're actually doing:
    $comment = "My lawyer is named will"; for ($new = $comment) { $comment = &doit($comment); }
    Okay, this is probably not what you intend. This takes $new, and sets it equal to $comment. Then this is treated as a list (of 1 item), which is assigned to $_ in the for loop (the s// will by default work on $_), and then $comment is set equal to the result of doit().
    sub doit{ $go = ";gie/moT/lliw/s ;gie/reknaB/reywal/s ;gie/yenraB/derf/s";
    This sets $go equal to that string.
    $com = join("", reverse split(//, $go));
    This sets $com equal to the result of this.
    return $com; } print $new;
    which is then returned ($new being set equal to that).

    It seems you want to _run_ those searches against $new. You'll want an eval() statement to do that. (Why is left to your own twisted goals). I suggest you study the for() loop because I suspect you are misunderstanding what it is doing.

    Update: eval() can be a security risk if you are running anything that can be affected by user input, particularly on a web page. I suggest you use perl's taint mode, and CGI.pm

      Here's a cleaned up version with some explanatory text. hope it helps, I have no idea why you would want to do this.

      #!/usr/bin/perl -wT #warnings and Taint checking on, see perlsec #CGI scripts should almost always use CGI.pm use CGI; use strict; #strict is your friend my $q = new CGI; print $q->header(); #print the header my $comment = "My lawyer is named will"; #this loops over the list in the parens, aliasing $new to each in turn #pointless, but presumably you anticipate having more than one in the +list for my $new ($comment) { $new = doit($new); #We act on $new, which will affect whichever lis +t element we're on } print $comment; #$comment, not $new. $new was only inside the loop sub doit{ my ($passed_string) = @_; #get the list we're passed, drop all but + first item #Note that I removed the "e" flags below, you aren't interpreting an +ything my $go = ";gi/moT/lliw/s ;gi/reknaB/reywal/s ;gi/yenraB/derf/s"; my $com = scalar reverse $go; $_ = $passed_string; #so that s// will work on it. eval $com or die $!; return $_; }
      Update: Cleaned it up a bit, thanks to BazB and podmaster for the assist
        Thanks ! The Reason: The string is actually lots longer. I have collected a Looonnnggg list of cusswords, in several languages, and the substitutions are for moronic language entered in a comments form. I would rather not show all the words to delicate people, if I ever run across any that is, so I like the s/'s backwards in the script. For example:
        s/bit*h/barbie/ or s/wh*re/exwife/ etc.
        I will study eval and the security problems.
Re: newkid confused
by Zaxo (Archbishop) on Apr 05, 2002 at 21:53 UTC
    my $foo = "My lawyer is named will"; my $oof = scalar reverse $foo;
    You may find japhy's sexeger interesting.

    Update: Chady, it's a matter of self-documentation and of habit. By using explicit scalar() I say what I expect to happen, and with the habit of using it I can drop it into list context without concern. About the link, I'm delighted to have recommended it for a bowdlerware application.

    After Compline,
    Zaxo

      I've been always using my $oof = reverse $foo; is there any particular reason for the scalar? isn't it already in a scalar context? will it break someday?


      He who asks will be a fool for five minutes, but he who doesn't ask will remain a fool for life.

      Chady | http://chady.net/
        Your way is fine. Many people make it an explicit scalar reverse because it isn't always a scalar context. Take for example:
        my $foo = "This is not a palindrome"; print reverse $foo;
        print implies a list context, so reverse will take the list ($foo), and reverse it to ($foo) and print that result. Probably not what is intended. It also can take a while to debug, when the perfectly acceptable-looking reverse statement "doesn't work".

        Thus, if you get in the habit of being explicit about your context, you don't get caught.