我有一个要转换为JSON字符串的数组。元素之一具有反勾号。当我尝试在外壳中运行命令时,这将导致错误:
data = [["305", "John Smith", "Amy Smith`", "10/11/2008", "Medical", {"page_count"=>4}]]
json_str = data.to_json.gsub('"','\"')
cmd = "node myscript.js #{json_str}"
Open3.popen3(cmd) do |stdin, stdout, stderr, wait_thr|
output = [stdout.read, stderr.read]
end
Error retrieving data: sh: 1: Syntax error: EOF in backquote substitution
一个明显的解决方案是逃避反引号:
json_str = data.to_json.gsub('"','\"').gsub('`','\\\`')
但是我想转义所有可能引起isuse的特殊shell字符。 Ruby的shellescape对字符串进行转义,以便可以在Bourne shell命令行中安全地使用它。这是一个示例:
argv = "It's better to give than to receive".shellescape
argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
但是看看当我将其应用于JSON字符串时会发生什么:
data = [["305", "John Smith", "Amy Smith`", "10/11/2008", "Medical", {"page_count"=>4}]]
data = data.to_json
=> "[[\"305\",\"John Smith\",\"Amy Smith`\",\"10/11/2008\",\"Medical\",{\"page_count\":4}]]"
data = data.to_json.shellescape
=>“ \\” \\\\“ \ [\ [\\\\\\\\”“ 305 \\\\\\\\\”,\\\\\\\“ John \ Smith \\\\\\\\“,\\\\\\\\” Amy \ Smith \`\\\\\\\\\“,\\\\\\\”“ 2008年10月11日\\ \\\\\\“,\\\\\\\\”医疗\\\\\\\\“,\ {\\\\\\\” page_count \\\\\\\\\“: 4 \} \] \] \\\\“ \\”“
很明显,这会引发如下错误:
SyntaxError: Unexpected token \ in JSON at position 0
发生的事情是,shellescape也将转义空格,因为shell要求转义空格。但是拥有空格是有效且必要的JSON。那么,如何在不破坏JSON的情况下转义会导致命令错误的shell字符?
答案 0 :(得分:4)
外壳是供人类使用的,而不是供机器使用的。让机器产生外壳命令是一种代码气味,表明您在错误的层进行自动化。
跳过外壳,然后使用所需的参数运行程序:
data = [["305", "John Smith", "Amy Smith`", "10/11/2008", "Medical", {"page_count"=>4}]]
json_str = data.to_json
Open3.popen3("node", "myscript.js", json_str) do |stdin, stdout, stderr, wait_thr|
output = [stdout.read, stderr.read]
end
由于不涉及任何外壳,因此没有人类逃避关心的愚蠢行为。