Search code examples
bashperlsyntaxquoting

How can I escape double quotes in the system command in this perl oneliner?


For my edification, I'd like to find out how to escape quotes within the system command in the following perl oneliner:

$ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'

without using the \" escape sequence, in the manner shown here: https://stackoverflow.com/a/1250279/3367247

(Obviously this command does nothing useful; it just prints filenames that have spaces in them. But it serves to explain my problem succintly.)

I tried the following (pardon the images, but I have found highlighting easiest to decipher the quoting):

  1. system command with double quotes: system("echo "$_"") enter image description here

Code: $ ls -p | grep -v / | perl -lane 'system("echo ''"''$_''"''");'

  1. system command with single quotes: system('echo "$_"') enter image description here

Code: $ ls -p | grep -v / | perl -lane 'system('"'"'echo "$_"'"'"');'

Neither of these work. Is there a way to accomplish this in the manner of the linked answer?

EDIT: I need double-quotes around the $_ in the echo command because the string in $_ contains parentheses, not because it contains spaces, as I originally thought.


Solution

  • I'd like to find out how to escape quotes within the system command in the following perl oneliner:

    $ ls -p | grep -v / | perl -lane 'system("echo \"$_\"");'
    

    without using the \" escape sequence, in the manner shown here: [...]

    Those examples are for escaping single quotes, your example uses double quotes \"$_\". In Bash everything within single quote are taken literally (except the single quote itself), the same is not true for that within double quotes. For example a $ within double quotes are not a literal $ but indicates that a variable expansion is to follow.

    Now, in your command there are three levels of quote interpretation.

    • First the outer shell (the command line):

      perl -lane 'system("echo \"$_\"");'
      
    • Then the perl interpreter:

      system("echo \"$_\");
      
    • Then a second shell (here, Bash is used):

      echo "xxx"
      

    where xxx is the expansion of $_ in the perl script

    Your command does not contain any internal single quotes, so there is no need to use the Bash quoting constructs for escaping single quotes, like

    It's fine  -> 'It'"'"'s fine'
    

    or

    It's fine  -> 'It'\''s fine'
    

    Further, you need to escape the double quote in the perl script

    system("echo \"$_\"")
    

    since they are inside double quotes, alternatively you could remove them since echo does not need double quotes here:

    system("echo $_")
    

    would work fine, or you could do as proposed in the comments:

    system(qq/echo "$_"/)
    

    or use the LIST form of system with more than one argument

    system("/bin/echo", $_)
    

    However, if you wanted to use single quotes, for example:

    system('echo ' . $_)
    

    you would need to invoke the shell's single quote escapes:

    'system('"'"'echo ''"' . $_)'
    

    or (using double quotes):

    "system('echo ' . "'$'"_)"