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

I want to unescape any backslash-escaped characters in strings entered by the user, so if the user enters:
Name:\tFrank\nAge:\t32
I want to print:
Name:   Frank
Age:    32
I don't want to interpolate variables, so I don't think I can abuse eval.

Replies are listed 'Best First'.
Re: unescape a user-entered string?
by simonm (Vicar) on May 30, 2004 at 16:37 UTC
      Well, I wanted this to be standalone but using unprintable() is attractive. Hmmm...standalone...attractive...standalone...attractive... Hard to choose now :)
Re: unescape a user-entered string?
by Zaxo (Archbishop) on May 30, 2004 at 16:43 UTC

    It depends on what keystrokes you mean. If your user is hitting the Tab key, then you only need print whay you get. If they are using backwhack and 't', you will have to translate somehow.

    You are wise to want to avoid eval of user input. How about a simple substitution?

    $_ = 'Name:\tFrank\nAge:\t32'; s/\\t/\t/g; s/\\n/\n/g; print;

    After Compline,
    Zaxo

      Yeah that would work. I was wondering if I was missing a simpler option
Re: unescape a user-entered string?
by hv (Prior) on May 30, 2004 at 22:07 UTC

    Hmm, maybe it is easier to invert it - escape the variables, then eval:

    $string =~ s/(\\.)|([\$\@])/$2 ? "\\$2" : $1/gse; $new = eval qq{qq{$string}};

    I can't offhand think of any way to introduce unwanted interpolation that this doesn't cover, but you'd obviously want to think about it more carefully than I if going this route. :)

    Hugo

Re: unescape a user-entered string?
by Happy-the-monk (Canon) on May 30, 2004 at 17:09 UTC

    I might be missing something?
    If it's just about printing, Perl's print will DWYM as long as the string is inside double quotes "..." or qq(...)

    Cheers, Sören

      (I'm the original poster, BTW...forgot to log in) The string is inside a variable, having been read from the user:
      $string = <>; print $string;
      So quotes don't help
Re: unescape a user-entered string?
by bart (Canon) on May 31, 2004 at 12:01 UTC
    Here's some code I've been using to both escape and unescape strings. One of its good points is its extensible nature. Now it escapes/unescapes newlines as '\n', tabs as '\t' and backslashes as double backslashes. You shouldn't forget about those, how else would you want to allow a user to enter any text they like, like a backslash followed by an 'n'?

    I would believe that by mere inspection of the code, it is clear how to extend it.

    BEGIN { use Regex::PreSuf; my %escape = ( "\n" => '\\n', "\t" => '\\t', "\\" => '\\\\'); my $escape = presuf(keys %escape); my %unescape = reverse %escape; my $unescape = presuf(keys %unescape); sub escape { local $_ = shift; s/($escape)/$escape{$1}/go; $_; } sub unescape { local $_ = shift; s/($unescape)/$unescape{$1}/go; $_; } }
    The BEGIN block is only desirable if you just paste this code into your script. The idea is that the hash and regex will be properly initialised at the time you try to actually use it one of these functions.

    I do have some doubts on the choice of function names, though. They're not actually saying much.

    p.s. You do need the latest patched version for Regex::PreSuf, as the previous version couldn't properly handle strings with embedded newlines.