Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

reverse quotemeta?

by sparky8342 (Acolyte)
on Jun 26, 2001 at 19:29 UTC ( [id://91629]=perlquestion: print w/replies, xml ) Need Help??

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

Hi,
If you have a string $x = '\n', is there any way to turn the \n back into a real carriage return?
Thanks

Replies are listed 'Best First'.
Re: reverse quotemeta?
by japhy (Canon) on Jun 26, 2001 at 20:04 UTC
    You're asking, "how can I generally turn escape sequences into what they correspond to", right?
    ### updated (thanks, Abigail) ### Unicode NOT included sub expand_escapes { local $_ = shift; s{ ( \\ (?: x[A-Fa-f0-9]{0,2} # hex escape | 0[0-7]{0,3} # octal escape | c. # ctrl-escape | . # any other ) ) }{qq["$1"]}geexs; return $_; }


    japhy -- Perl and Regex Hacker
      Nice... but, hex escapes and octal escapes aren't fixed width. "\xA" is a newline, and octal escapes (which need a leading 0 that you have also forgotten) can have less than 3 octets as well.

      And be aware of Unicode. There will be lots more escape sequences with Unicode.

      -- Abigail

        In Perl's double quoted strings, octal escapes don't need a leading zero.

        japhy, please don't make silent updates to your node. (I'm used to update notes using bold)

        (updated)

                - tye (but my friends call me "Tye")
      Yeah, if only things were so simple. "\0001" is one character according to your subroutine. However, Perl thinks it's two. As tye pointed out, leading 0s aren't required (but allowed). But for octets above 077 a leading 0 doesn't seem to be allowed. And for octets above 377, you will move into Unicode territory, whether you want it or not. "\400" causes Perl to think things are really messed up.

      -- Abigail

Re: reverse quotemeta?
by suaveant (Parson) on Jun 26, 2001 at 19:39 UTC
    You could do...
    $x =~ s/(?<!\\)\\n/\n/g;
    the (?<!\\) is to make sure the \ in \n isn't escaped.

                    - Ant

      Your substitution will correctly leave the \n in \\n alone, but what about \\\n? The backslash preceeding \n is itself preceeded by a backslash, so the \n should be converted in that case. \\\\n, on the other hand, shouldn't get the \n converted.

      What is needed is something to match pairs of backslashes before the \n, like this: s/((?<!\\)(?:\\\\)*)\\n/$1\n/g;

        If you are going to do that, then you need to unescape the backslashes as well! While you can do that via (something close to one of these):

        s#(?<!\\)((?:\\\\)*)\\n# '\\'x(length($1)/2) . "\n" #ge; # or s#(?<!\\)(\\*)\1\\n#$1\n#g;
        I find that having to escape your backslashes only when they preceed a (desired) newline to be confusing so I'd go with japhy's excellent sugestion or perhaps: s#\\([\\n])# $1 eq "n" ? "\n" : $1 #ge

                - tye (but my friends call me "Tye")
Re: reverse quotemeta?
by Hofmator (Curate) on Jun 26, 2001 at 19:38 UTC

    just replace it

    $x = '\n'; $x =~ s/(?<!\\)\\n/\n/g; print $x;

    Update: Well, I was first but I had to pay my price :) - as suaveant correctly pointed out, you have to take care of the special case of an escaped escape so I fixed that.

    What would be interesting is a simple general solution which does that transformation not only for \n but also \t, \cC, \xFF, ... but I'm lost there. Anybody??

    -- Hofmator

Re: reverse quotemeta?
by chromatic (Archbishop) on Jun 26, 2001 at 23:21 UTC
    Not the best general solution, but at least I don't have to write a nasty regex:
    my $x = '\n'; my $string = '$x = "' . qq|$x| . '";'; eval $string; print "->$x<-\n";
    It's missing error handling and if $x contains any unescaped single quotes, it'll break. Still, it's another way to do it.
Re: reverse quotemeta?
by nardo (Friar) on Jun 26, 2001 at 19:39 UTC
    This isn't a reverse quotemeta since quotemeta won't turn a newline into '\n'
    eval("\$x = \"$x\"");
    should do what you want.

    Update This is not ideal, although this will perform all escaped character conversions, if your string has an unescaped '$' in it then it will be replaced by a variable. For example: 'It costs $1.25' the '$1' will be replaced with the contents of $1
Re: reverse quotemeta?
by RatArsed (Monk) on Jun 26, 2001 at 19:54 UTC
    $x =~ s/\\n/\n/gi; I'm sure there's a better way to do it using tr///, but my brain is fried for today...

    --
    RatArsed

      I don't think that's correct.
      tr/// can only do character-by-character substitutions, so \n as an escaped new line would be 2.

      You'd also have to consider any other extenuating circumstances, like having an escaped slash preceding a normal n.
      Update
      So this perl hacker walks into a bar...

      and says "ouch!"
      thank you all.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://91629]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2024-03-29 15:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found