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

I'm wrestling with a simple config file that I want to contain items of formatted paragraph/text. For some reason, perhaps sillyness on my part one entry might be: TEXT=Hello\nWorld\n! (rather than actual newlines in the input file) I want to then print that text out as if I coded print "Hello\nWorld\n!" It seems I'm wanting to interpolate a variable twice.

I thought about running the variable of input through  s/\\n/\n/g

That works...but my instinct is I could do be doing this differently/better. How would you do it?

Replies are listed 'Best First'.
Re: print real newlines in place of literal ones
by particle (Vicar) on Jun 05, 2003 at 18:58 UTC

    there are many ways i do it, depending on the situation...

    1. pick a seperator that won't appear in your text, like \0. set $/ to this value when parsing the config file
    2. use perl's heredoc syntax, and do the file
    3. use one of the fine Config modules from CPAN
    4. RECOMMENDED use my favourite config module, YAML.

    ~Particle *accelerates*

Re: print real newlines in place of literal ones
by pzbagel (Chaplain) on Jun 05, 2003 at 19:09 UTC

    The problem is that \n is not a variable, you can't interpolate it, it is a meta character that the print, etc. understand. When you read in your key/value pair of TEXT=Hello\nWorld\n! you are reading in a literal "\" and a literal "n", not the metacharacter "\n". Once it is read in as "\" and "n", no amount of interpolation will make it a meta character. For all intents and purposes, you can look at your input text as: "Hello\\nWorld\\n!".

    You were on the right track with your substition.

    HTH

Re: print real newlines in place of literal ones
by tos (Deacon) on Jun 05, 2003 at 18:59 UTC
    Hi

    I'm not sure if i understand what you mean.

    If you want the literal newlines to be printed try something like this

    perl -we 'print qw/Hello\nWorld\n!/' Hello\nWorld\n!
    if not simply print out the string as it is.
    # perl -we 'print "Hello\nWorld\n!"' Hello World !
Re: print real newlines in place of literal ones
by CountZero (Bishop) on Jun 05, 2003 at 19:13 UTC

    In its infinite wisdom, the Camel Book says:

    You may only interpolate expressions that begin with $ or @, because those are the two characters (along with backslash) that the string parser looks for.(p. 62)

    Interpolation is extremely powerful but strictly controlled in Perl. It happens only inside double quotes, and in certain other "double-quotish" operations(p. 63)

    So it seems that your solution is the only way.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: print real newlines in place of literal ones
by Aragorn (Curate) on Jun 05, 2003 at 21:24 UTC
    Treat the Hello\nWorld\n! as a piece of Perl code to be evaluated:
    #!/usr/bin/perl use strict; use warnings; my $line = 'TEXT=Hello\nWorld!\n'; # No interpolation $line =~ s/^TEXT=//g; print "$line\n"; my $interpolated = eval "qq{$line}"; print $interpolated;
    Output:
    Hello\nWorld!\n Hello World!

    Arjen

      Uh...

      Just a note that this can be a little dangerous. In the worst case, the eval will mess up. But if someone just wants to mess with you, they can do a very nice job of it. Observe:

      my $line = 'TEXT=};print `ps`;print "Your machine is h4x0r3d!!$/";qq{H +ello\nWorld!\n'; .. OUTPUT: PID TT STAT TIME COMMAND 5808 p0 S 0:00.02 _su (csh) 5816 p0 S+ 0:00.01 perl mylittleprogram.pl 5817 p0 R+ 0:00.00 ps 149 v0 IWs+ 0:00.00 /usr/libexec/getty Pc ttyv0 Your machine is h4x0red!! Hello World #

      I'm just showing that this can be a little dangerous but if you're the only one who is writing to the config file, you'll need to make certain you never use } or you'll most likely get $interpolated = undef. Of course, a prankster could put some code in the config file as I just showed and have it do a lot of nifty things and you still get the output you expected. So it could be some time before you'd realize anything is wrong at all. Of course, what are the chances of that? ;-)

      antirice    
      The first rule of Perl club is - use Perl
      The
      ith rule of Perl club is - follow rule i - 1 for i > 1

        I know ;-) But the previous posts basically asserted that without some substitution, it wasn't possible to do this. When using this technique, you'll want to turn on taint checking and thus be forced to inspect the input (the TEXT=... in this case). But while doing that, it's probably easier to make the substitution right away, thereby removing the need for the eval altogether!

        Sometimes, using this technique (or the do EXPR function) is useful for writing a script which uses a configuration file without using a special module for it. It's just another way of doing something, and can be very convenient sometimes.

        Arjen