简体   繁体   中英

Quotes in Quotes in Quotes in a “Linux” Shell

Let's say I have shell programs a,b,c, each one executing a command from the other one. For some reasons, I need quotes. Example:

a 'b 'c 'echo test'''

So a shall call b, which shall call c, which will call 'echo test'. You already see that my quotes will be wrong interpreted. Also, note that a, b, and c are C-programs calling system().

Is there any solution to do that, preserving the quotes?

You have to escape the inner quotes. Unfortunately it's not really possible for single-quotes, so I'd use double-quotes for all the outer levels and single-quotes for the innermost quotes, because double-quoted string can contain single-quotes without escaping. So the result should be:

a "b \"c 'echo test'\""

Note, that you need to add backslashes for each level you need to pass through, so if " were used at the last level, you'd need

a "b \"c \\\"echo test\\\"\""

and next level would get to 7 backslashes and so on.

I have no ready solution for C, but in this case, it is advisable to take your string-to-be-quoted, replace every ' with '\\'' and enclose the whole stuff in ' .

  1. The innermost part is echo test That can happily be put in '' and given to c : c 'echo test' .
  2. Then you want to give that string to b . Here it starts, because the said string contains ' s, so you do ' + c '\\''echo test'\\'' + ' which you give to b: b 'c '\\''echo test'\\''' . What happens here? You have concatenated several concatenated parts for b 's argument:

    1. 'c ', which becomes just c `,
    2. \\' , which becomes '
    3. 'echo test' , which is echo test after stripping the quotes,
    4. \\' again -> ' , and
    5. '' which is nothing and only exists because there is a ' at the end of the original string. It can be omitted if processed manually, but isn't worth the effort in an algorithm.

    So you get c 'echo test' after dequoting that, which shows that the said algorithm should work.

  3. Now you do this process to b 'c '\\''echo test'\\''' again in order to have an argument for a : so you'll get a 'b '\\''c '\\''\\'\\'''\\''echo test'\\''\\'\\'''\\'''\\''' .

  4. Even trickier: you now want to put that in a C string, so you'll have to double the \\ s: system("a 'b '\\\\''c '\\\\''\\\\'\\\\'''\\\\''echo test'\\\\''\\\\'\\\\'''\\\\'''\\\\'''"); .

If you do the said optimization on starting, ending and successive ' s, you get

b 'c '\''echo test'\'

and

a 'b '\''c '\''\'\'\''echo test'\''\'\'

resp.

system("a 'b '\\''c '\\''\\'\\'\\''echo test'\\''\\'\\'");

.

Alternatively, you could work without the ' and just quote the spaces and the '\\'s, but that would probably even trickier...

Let me try:

  1. c: echo test -> echo\\ test -> c echo\\ test .
  2. b: bc\\ echo\\\\\\ test .
  3. a: ab\\ c\\\\\\ echo\\\\\\\\\\\\\\ test .
  4. system: system("ab\\\\ c\\\\\\\\\\\\ echo\\\\\\\\\\\\\\\\\\\\\\\\\\\\ test") .

Quote ugly, but it works.

Tested with

#!/usr/bin/env python
import sys

import subprocess
sp=subprocess.Popen(sys.argv[1], shell=True, stdout=subprocess.PIPE)
for line in sp.stdout:
    print "%s> %s" % (sys.argv[0], line),
exit(sp.wait())

as a , b and c and

import os
print 1
os.system("a 'b '\\''c '\\''\\'\\'''\\''echo test'\\''\\'\\'''\\'''\\'''")
print 2
os.system("a 'b '\\''c '\\''\\'\\'\\''echo test'\\''\\'\\'")
print 3
os.system("a b\\ c\\\\\\ echo\\\\\\\\\\\\\\ test")

as test.py and called with

PATH=.:$PATH python -m test

As python has in this case the same quoting rules as C, it is a sufficient test.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM