我正在尝试制作一个脚本,该脚本需要保存要作为字符串运行的命令。有问题的字符串需要包含引号,当尝试执行它时,bash 会添加额外的引号字符,这在某些情况下会导致命令无法按预期运行。
这是一个示例脚本。在此示例脚本中运行的命令example
显然不会执行任何操作,它只会说command not found
,但是您仍然可以运行该脚本并查看我在说什么,因为我添加到了-x
该#!/bin/bash
行,以便打印出正在运行的确切命令。
例子:
#!/bin/bash -x
#command typed explicitly
example -options "-i filename"
#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}
为我运行此脚本的输出是(忽略两个“命令未找到”错误):
+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'
因此,您可以看到第一行当然按预期运行,给出了命令行参数:
-i filename
然而,尽管该echo
命令以同样可以完美执行的方式打印字符串,但当将字符串放在命令行上时,它会发生变化,并且传入的参数会变成
''-i' '文件名''
其中包含额外的引号字符,这导致我在真实脚本中使用的实际命令失败。
有什么办法可以防止这种情况发生吗?
答案1
如果您使用的是bash
,准确保存命令的最简单方法是将其放入数组中。如果您要运行的命令是:
example -options "-i filename"
您可以将其保存在数组变量中:
commandline=(example -options "-i filename")
然后,您可以通过 @ 扩展双引号内的数组来运行保存的命令:
"${commandline[@]}"
这里要知道的关键是,"'\
当直接在命令行中输入时,shell 对引号字符 () 的处理方式与在变量扩展中(如${commandstring}
.在命令行中,引号字符具有特殊的引用功能。在参数扩展中,它们只是普通的非特殊字符。因此,"-i filename"
是在命令行中键入时被解析为 的单个单词-i filename
,但变量中的相同字符扩展为单词"-i
和filename"
。
Bash常见问题解答 50更详细地涵盖了这个主题。