在命令替换中使用引号

时间:2016-10-17 19:32:42

标签: bash shell

我不明白为什么会这样做

dateCMD=$(date -d "4 hours ago")
echo $dateCMD
Tue Oct 18 02:20:34 AEDT 2016

这是有效的

dateCMD="date"
$dateCMD
Tue Oct 18 06:23:19 AEDT 2016

但不是这个

dateCMD='date -d "4 hours ago"'
$($dateCMD)
date: extra operand ‘ago"’

如何让最后一个案例发挥作用?

3 个答案:

答案 0 :(得分:6)

简短的回答:你不想这样做。改为使用函数。

dateCMD () {
  date -d "4 hours ago"
}

dateCMD

长答案:参数值中的引号不是“语法”引号;它们只是常规数据。当你写

dateCMD='date -d "4 hours ago"'
$($dateCMD)

评估如下:

  1. $dateCMD扩展为date -d "4 hours ago"
  2. 扩展分为date-d"4hoursago"。报价未经特别处理。
  3. 第一个单词date被视为命令,其余单词作为不同的参数传递。
  4. date"4作为-d选项的参数。由于date只接受一个额外的位置参数(格式字符串),因此需要hours作为该参数,然后抱怨ago是一个额外的操作数。

答案 1 :(得分:2)

使用BASH数组使其工作:

dateCMD=(date -d "4 hours ago")
"${dateCMD[@]}"
Mon Oct 17 11:38:54 EDT 2016

我正在输入你的引用问题的解释,但后来我注意到@chepner解释得非常好,所以避免在我的答案中添加多余的信息。

答案 2 :(得分:0)

要使最后一个案例起作用,您可以使用eval

当然,如果没有完全验证该输入,则不应在任何用户输入上使用eval。

dateCMD='date -d "4 hours ago"'
eval $dateCMD