使用bash执行某些命令时遇到问题。让我们说我有一个简单的bash脚本:
#!/bin/bash
cmd="sh -c \"ls\""
$cmd
这一切都很好。但是,如果我更改命令的参数以包含空格:
#!/bin/bash
cmd="sh -c \"ls -a\""
$cmd
然后它抛出-a": 1: -a": Syntax error: Unterminated quoted string
错误。似乎bash正确地注意到开放引用,但它停止在第一个空间寻找结束引用。如果我将$cmd
更改为echo $cmd
,则会按预期返回sh -c "ls -a"
。如果我在终端中执行此命令一切正常,但$(./mysh.sh)
失败并出现相同的错误。
我尝试使用\
或“双重逃脱”来逃避空间。引用\\\"
(愚蠢的想法,但值得一试)。谁能解释一下这里发生了什么?
答案 0 :(得分:5)
最好在函数中存储命令:
cmd() {
sh -c "ls -a"
}
cmd
或者在数组中:
cmd=(sh -c "ls -a")
"${cmd[@]}"
使用纯字符串变量根本不起作用。您必须使用eval
not a great idea。功能要好得多。
cmd="sh -c \"ls -a\""
eval "$cmd"
答案 1 :(得分:3)
引用规则的重复应用可能很复杂。首先,我将解释出现了什么问题:
cmd="sh -c \"ls -a\""
$cmd
Bash在执行$ cmd时所做的第一件事是将其拆分为空白字符:所以你得到一个带有三个参数的命令,相当于:
sh -c "\"ls" "-a\""
你已经可以看到这出错了。已经发布了一些解决方案,但是通常对于命令将要经历的每个级别的shell命令处理,您需要提供另一级别的保护字符来维护原始的预期含义:
# To execute the command "ls -a" in a shell:
sh -c "ls -a"
# Two shells deep:
sh -c "sh -c ls\\ -a" # Backslash protects space from being treated as an argument separator by first level of shell processing
如果可以的话,最好避免重复使用报价保护......
答案 2 :(得分:0)
cmd="sh -c \"ls -a\""
eval $cmd