Shells, quoting, and one-liners
The goal this post is to show how to call Perl and Python one-liners from a shell. We want to be able to use bash on Linux, and cmd or PowerShell on Windows, ideally with the same code in all three shells.
BashBash interprets text inside double quotes but not in single quotes. So if you want to send a string to a program unmolested, you surround it with single quotes.
For example, suppose I want to write a Perl one-line program to print hello. This works:
perl -e 'print "hello\n"'
The single quotes tell the shell to pass what's inside to perl without doing anything to it.
The corresponding Python example would be
python -c 'print("hello\n")'
and this also works.
Cmd and PowerShellFor reasons I don't understand, the Perl example above works from cmd, but the Python example does not.
And neither example works in PowerShell. This is particularly puzzling since PowerShell follows basically the same quoting rules as bash: double quotes interpolate but single quotes do not.
WorkaroundsThere are ways to fix the problems with cmd and PowerShell without breaking bash.
PerlPerl has a handy feature for avoiding confusion over quotes: you can use q{} for single quotes and qq{} for double quotes. If I write the Perl example as
perl -e 'print qq{hello\n}'
then it works everywhere: bash, cmd, and PowerShell.
PythonPython makes no distinction between single and double quotes, so you can reverse the role of single and double quotes to avoid quoting confusion. The code
python -c "print('hello\n')"
works everywhere.
Printing quote marksIn the previous section we said we can get around problems in Perl by using q{} and qq{}, and get around problems in Python by switching to double quotes on the outside and single quotes on the inside. But what if we wanted to print a single or double quote mark, such as printing 'hello' or "hello"?
You can escape single quotes with \' and double quotes with \", but you run into things that work on cmd but not on bash, or work on bash but not in PowerShell, etc.
One sure-fire way to make quotes work, in Perl and in Python, and on every shell we're considering, is to denote quotes by their Unicode values, i.e. to use \x27 for single quotes and \x22 for double quotes. The one-liners
perl -e 'print qq{\x27hello\x27\n}'
and
python -c "print('\x27hello\x27\n')"
print 'hello' in bash, cmd, and PowerShell.
And similarly
perl -e 'print qq{\x22hello\x22\n}'
and
python -c "print('\x22hello\x22\n')"
print "hello" in bash, cmd, and PowerShell.
Guidelines for portable one-linersIn summary, you can avoid problems with Perl one-liners by using q{} and qq{} inside code rather than single or double quotes. For Python one-liners, you can swap single quotes and double quotes.
On Linux (bash) surround code with single quotes. On Windows (cmd and PowerShell) surround code with double quotes.
Use character codes for literal quote characters. This isn't necessary, but if you do this you won't have to remember how quotes and escapes work on different platforms.
Further readingThe post Shells, quoting, and one-liners first appeared on John D. Cook.