In Powershell, I would like to run the following command:
bash -c "echo 'hello world!'"
(I know I could use echo
or Write-Host
directly, but I need to use bash -c
) and I would like hello
to be surrounded by single quotes and world
by double quotes. In other words, I'd like the following output:
'hello' "world"!
I should I escape those quotation marks?
Since you are calling a program (e.g. bash
) "normal" rules to escape quotation characters don't necessarily work the "same" way. Instead of PowerShell interpreting the string, (which would normally follow "normal" quotation rules), you are passing arguments to the program. This is interpreted in a completely different manner.
TLDR: To escape quotation characters requires the following command:
bash -c "echo \'Hello\' \\\""World\\\""!"
Outputs:
'Hello' "World"!
Now that looks awfully complicated. So, let's break it down.
First, what is the correct command in bash
to output the desired quotation? Let's try regular quotes:
HAL9256@HAL9000:~$ echo 'Hello' "World"!
Hello World!
No quotes. Oh yeah! I have to escape them. In bash
I have to escape them with backslashes (\
):
HAL9256@HAL9000:~$ echo \'Hello\' \"World\"!
'Hello' "World"!
There we have it. We have to use a single backslash to properly escape our quotes in bash
. So let's plug that into PowerShell:
PS C:\> bash -c "echo \'Hello\' \"World\"!"
/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file
Well that didn't work. Oh right, in PowerShell we have to escape the double quotes with backticks (`) because they are inside a set of double quotes:
PS C:\> bash -c "echo \'Hello\' \`"World\`"!"
'Hello' World!
Well, that didn't error out, but still not what we want. The quotes are still not escaped properly. Grrr. This is where you start typing in 100 different combinations of characters to find out what the right combination is ;-).
Or, let's go back to bash
and figure out what may be going on. First, let's remember that the string that is being echo
ed is being interpreted like a string. So let's put double quotes around our echo statement so that it is being treated like a string, and see what it does. Remember, what we want out of this is the output to be the same bash
command earlier, with the backslashes:
HAL9256@HAL9000:~$ echo "\'Hello\' \"World\"!"
\'Hello\' "World"!
Well, ultimately what we want to send to bash
is that original string with the backslashes. Here we can see that the backslashes are escaping the double quotes and disappearing. So, adding more slashes:
HAL9256@HAL9000:~$ echo "\'Hello\' \\"World\\"!"
\'Hello\' \World\!
Oh, great. We escaped the backslashes. Like Inception, keep adding escape characters till it works....
HAL9256@HAL9000:~$ echo "\'Hello\' \\\"World\\\"!"
\'Hello\' \"World\"!
There! we have our output. Now we have to enter it into PowerShell:
PS C:\> bash -c "echo \'Hello\' \\\"World\\\"!"
/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file
Oh! yes the same error as before. We have to remember to escape the double quotes in PowerShell with a backtick:
PS C:\> bash -c "echo \'Hello\' \\\`"World\\\`"!"
'Hello' "World"!
Success! It only took a lot of escaping, both bash
-wize, and PowerShell-wize. Another way, and in my opinion, easier to understand way to escape inside double quotes is to use two double quotes instead of the backtick like so:
PS C:\> bash -c "echo \'Hello\' \\\""World\\\""!"
'Hello' "World"!