0

I am trying to echo I say "Hello, World!" with bash -c. This is (some of) what I have tried:

$ bash -c "echo I say \"Hello, World"'!'"\""
$ bash -c "echo I say "'"'"Hello, World"'!'"\""
$ bash -c "echo I say """Hello, World"""'!'
$ bash -c $'echo I say \"Hello, World!\"'
$ bash -c 'echo I say "Hello, World!"'

They all print

I say Hello, World!

How can I show the quotes ?

2 Answers 2

4

The problem lies in the fact that you have nested quotes, which makes quoting somewhat involved. Since you don't have a "comprehensive" quote around your arguments to echo, all your attempts (except for your 3rd attempt(1)) are actually passing three arguments to echo, which are all subject to quote removal:

  • I
  • say
  • Hello, World!

The key point is that upon interpretation of the "outer" command, the outer quotes of the argument to bash -c are removed. The inner quotes remain, either because they are escaped or because they are of different type than the outer ones.

Then, when the bash instance you explicitly called processes that argument (the "inner" command), it itself performs quote-removal when interpreting the arguments to the echo call. Thus, the quotes you put around Hello, World! will ensure that this is considered one argument to echo, but be removed in the same process (and thereby lost to echo).

Since you don't need variable expansion in the ("inner") echo command, I would go with the single-quote syntax as follows:

bash -c 'echo "I say \"Hello, World\"!"'

That way you are passing one single argument to echo, and the quote-escaping inside the double-quotes will work as expected.


(1) In the 3rd attempt you show, you are actually passing 2 arguments to bash -c:

  • echo I say Hello, and
  • World!

leading to four arguments to echo seen by the "inner" command. This is because your attempt to "interrupt" the outer double-quotes with """ doesn't work that way - instead, the first of these double-quotes mean that the starting double-quote of the bash -c argument is closed after the space. This is then seen as being followed by an empty double-quoted string, and then by an unquoted Hello,. All these are concatenated because there is no space in between them.

Then, since the space following is unprotected, the outer bash will now consider the remainder a second argument, starting with the (again unquoted) World, a double-quoted empty string, and then an opened-but-unclosed double-quoted string containing '!'. The fact that it is not correctly closed is masked by the error message you should receive about an "event not found", since the starting double-quote makes the following single-quote merely a character to-be-printed, whereby the ! is no longer protected from interpretation as history reference.

1

If you dont care about POSIX-compliance, you can work around the problem by adding -e to echo and print the ascii-codes for " which would be \x22 (in hex) or \042 (in octal).

bash -c 'echo -e "I say \x22Hello, World\x22"'

bash -c 'echo -e "I say \042Hello, World\042"'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .