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

I have the following perl script:


#!/usr/bin/perl -w use strict; use Getopt::Long; my $string; GetOptions( "string=s" => \$string ); printf("string = $string\n");

I have the following shell script that calls the above perl script:


#!/bin/tcsh /home/perl_scripts/pass_newline_as_text.pl \ -string 'foo\nbar'

The output I would like to see is as follows:


string = foo bar

The actual output I'm seeing is the following:


string = foo\nbar

Is there a way to have the '\n' interpreted as an actual newline character by the perl script? I've tried enclosing the string in single and double quotes, and using 1-3 backslash escapes on the 'n' character but none of those work.

Replies are listed 'Best First'.
Re: passing newline in string argument
by haukex (Archbishop) on Aug 01, 2025 at 19:14 UTC

    This seems like a shell issue instead of a Perl question, because it appears the shell isn't interpreting \n as a newline. In other words, Perl is getting passed the literal 8-character string "foo\\nbar" from the shell.

    I'm unfortunately not well-versed in tcsh so the "best" solution I've found so far is:

    #!/bin/tcsh /home/perl_scripts/pass_newline_as_text.pl \ -string "foo\ bar"

    I would typically recommend against working around this in Perl, because if you start supporting "\\n" to "\n" translation in Perl, then the question is which escape codes do you want or need to support, and it quickly becomes overly complicated - see my three posts in this thread: Can't get \n or other character/translation escapes to interpolate if originally read from a data file

      "`/bin/echo -e 'foo\nbar'`" should work, as it does in bash, but I can't get it to :(

        Try

        "`/bin/echo -e \"foo\nbar\"`"
Re: passing newline in string argument
by ikegami (Patriarch) on Aug 02, 2025 at 00:02 UTC

    You didn't pass a Line Feed. You passed a Backslash and a Latin Small Letter N

    To Pass a Line Feed, you can use

    # tcsh -string 'foo\ bar'
    or
    # POSIX sh, ksh, bash, dash -string 'foo bar'
    or
    # POSIX sh, ksh, bash, dash -string "$( printf 'foo\nbar' )"
    or
    # bash -string $'foo\nbar'

    Is there a way to have the '\n' interpreted as an actual newline character by the perl script?

    s/\\n/\n/g

    But what if someone actually wants to provide the two characters \n? It's up to you to define your language and write a parser and interpreter for it.

    And don't forget that scripts that call your program would need an escaping function to provide user input to your program.

    It's far simpler to simply provide the correct string, which is why I led with that. Is there a way to have the '\n' interpreted as an actual newline character by the perl script?

      But what if someone actually wants to provide the two characters \n?

      Special_K, just for completeness, here's one common way - however, as we both said, this is only a workaround with its own caveats, and the problem should be fixed in the shell instead!

Re: passing newline in string argument
by NetWallah (Canon) on Aug 02, 2025 at 02:45 UTC
    $ perl -e 'use Getopt::Long;GetOptions( "string=s" => \my($string));ev +al qq|print("string = $string\n")|' - -string 'foo\nbar' string = foo bar

                    "If it happens once, it's a bug. If it happens twice, it's a feature. If it happens more than twice, it's a design philosophy."

      I think it's very well worth mentioning that eval is a massive security hole with untrusted input.

        > I think it's very well worth mentioning that eval is a massive security hole with untrusted input

        Strongly agree!

        For string eval that is; block eval (now spelled try in latest versions of Perl) is fine.

        See also: avoid string eval References

        👁️🍾👍🦟