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 '
.
echo test
That can happily be put in ''
and given to c
: c 'echo test'
. 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:
'c ', which becomes just
c `, \\'
, which becomes '
'echo test'
, which is echo test
after stripping the quotes, \\'
again -> '
, and ''
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.
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'\\''\\'\\'''\\'''\\'''
.
\\
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:
echo test
-> echo\\ test
-> c echo\\ test
. bc\\ echo\\\\\\ test
. ab\\ c\\\\\\ echo\\\\\\\\\\\\\\ test
. 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.