在bash中执行带有空格的参数的命令

时间:2014-03-28 17:26:45

标签: bash

使用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)失败并出现相同的错误。

我尝试使用\或“双重逃脱”来逃避空间。引用\\\"(愚蠢的想法,但值得一试)。谁能解释一下这里发生了什么?

3 个答案:

答案 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