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

I'm having some difficulty using a perl one-liner within a bash program. This works fine:

ifconfig | perl -e ' while (<>) { $_ =~ /inet addr:(10.[\d.]+)/; $host = `nslookup $1`; }; $host =~ /name = ([\S]+)./; print $1;'

However, this does not (bash complains about bad syntax, as if it's trying to parse the perl):

host=`ifconfig | perl -e ' while (<>) { $_ =~ /inet addr:(10.[\d.]+)/; $host = `nslookup $1`; }; $host =~ /name = ([\S]+)./; print $1;'`

Some people on the internet recommend replacing my single quote with a double quote, but this does not help. I'm posting this in perl because it seems perl-specific. For example, this awk line works great, and has the same single-quote-within-backtick structure:

IP=`ifconfig | awk 'BEGIN { FS = ": " } { print $2 }'`

Thoughts? No commentary on the fact that I should just write the whole program in perl, please. I would if I could.

Replies are listed 'Best First'.
Re: backticks and quotation trouble in bash
by LanX (Saint) on Dec 18, 2012 at 15:10 UTC
    It's a bash-quoting problem, since you can't nest backticks! ...`nslookup $1`...!

    But there is a Perl solution: try qx or even system within perl to avoid disambiguation.

    Cheers Rolf

      If it was a bash problem, why does the awk example work? Also, the tools you gave me are ways of calling bash from perl. I'm having trouble calling perl from bash.

        again ...qx/nslookup $1/ ... should do.

        > why does the awk example work?

        no nested backticks?

        > are ways of calling bash from perl

        exactly, thats the ill thing about your construct, your calling perl from bash to call a system command.

        Cheers Rolf

        UPDATE:

        > No commentary on the fact that I should just write the whole program in perl, please. I would if I could.

        LOL. This is a Perl help board, if you're not interested to learn our solutions you should consider hiring someone who does the tricky things for you.

        floobit:

        Because the awk example, as mentioned by LanX doesn't try to nest backticks.

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: backticks and quotation trouble in bash
by Anonymous Monk on Dec 18, 2012 at 22:19 UTC

    The alternative syntax for backticks in Bourne shell would be $( ... ):

    host=$(ifconfig | perl -e ' while (<>) { $_ =~ /inet addr:(10.[\d.]+)/ +; $host = `nslookup $1`; }; $host =~ /name = ([\S]+)./; print $1;')

    I'm not quite sure it's available in all Bourne-compatible shells, but it seems to work on the Debian Almquist shell so it's a fairly safe bet that it is.

    BTW, you should be able to split that command into two with a temporary variable or so and avoid the problem:

    ip=`ifconfig | perl -ne ' $_ =~ /inet addr:(10.[\d.]+)/ and print $1` host=`nslookup $ip | perl -ne '/name = ([\S]+)./; print $1;'`

      The $( ... ) syntax for command substitution is not alternative, but is in fact the preferred one according to the POSIX standard.

      Backticks/backquotes have long been considered legacy and are deprecated: they are hard to read, and nesting and quoting are problematic.

      In the new and more readable form, nesting "just works" and quotes have their own context within the command substitution so it's not necessary to escape them.

      See the POSIX documentation for more details.