【问题标题】:Executing command in bash with argument with space in it在bash中执行带有空格的参数的命令
【发布时间】:2014-03-28 17:26:44
【问题描述】:

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

我尝试使用\ 转义空格,或使用\\\" 进行“双转义”引号(愚蠢的想法,但值得一试)。谁能解释这里发生了什么?

【问题讨论】:

标签: bash


【解决方案1】:

最好将命令存储在函数中:

cmd() {
    sh -c "ls -a"
}
cmd

或者在数组中:

cmd=(sh -c "ls -a")
"${cmd[@]}"

使用纯字符串变量根本行不通。您必须使用eval,即not a great idea。功能要好很多。

cmd="sh -c \"ls -a\""
eval "$cmd"

【讨论】:

  • @BroiSatse:至于为什么eval 通常出于安全性 的原因不是一个好主意:它允许执行存储在一个字符串 - 如果将字符串交给你,你必须相信它的内容只会做你期望它做的事情。 eval 在有限和受控的情况下可能很好,但通常最好远离(并且通常有更好的选择,例如在这种情况下) - 请参阅 mywiki.wooledge.org/BashFAQ/048
  • @mklement0 很好的答案。这比我写的要好。
【解决方案2】:

引用规则的重复应用可能很复杂。首先,我将解释发生了什么问题:

cmd="sh -c \"ls -a\""
$cmd

在执行 $cmd 时,Bash 所做的第一件事就是将其拆分为空格字符:因此您会得到一个带有三个参数的命令,相当于:

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

如果可以的话,最好避免重复应用引用保护...

【讨论】:

    【解决方案3】:
    cmd="sh -c \"ls -a\""
    eval $cmd
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多