![如何在不额外引用的情况下将 bash 变量作为命令运行?](https://linux22.com/image/57352/%E5%A6%82%E4%BD%95%E5%9C%A8%E4%B8%8D%E9%A2%9D%E5%A4%96%E5%BC%95%E7%94%A8%E7%9A%84%E6%83%85%E5%86%B5%E4%B8%8B%E5%B0%86%20bash%20%E5%8F%98%E9%87%8F%E4%BD%9C%E4%B8%BA%E5%91%BD%E4%BB%A4%E8%BF%90%E8%A1%8C%EF%BC%9F%20.png)
我正在尝试制作一个脚本,该脚本需要保存要作为字符串运行的命令。有问题的字符串需要包含引号,当尝试执行它时,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更详细地涵盖了这个主题。