在一个相当大的项目中,我遇到了以下问题:在 bash 脚本中计算正确的命令时,我无法使脚本尊重带有空白的单个参数所需的双引号。
$ ./testo "two three"
ls -l "two three_DD_FF" # <- Why does it look for two files HERE??
ls: cannot access '"two': No such file or directory
ls: cannot access 'three_DD_FF"': No such file or directory
“二三”是单一参数。
使用 Two_Three 我的代码可以正常工作,正如预期的那样:
$ ./testo two_three
ls -l "two_three_DD_FF"
ls: cannot access '"two_three_DD_FF"': No such file or directory
这是我能想到的基本通用代码:
#!/usr/bin/bash
cmd="ls -l"
trio=""'"'"${1}_DD"
trio="${cmd} ${trio}_FF"'"'""
echo ${trio}
${trio}
(对于看起来奇怪的强引用,我没有找到比上面的方法更奇怪的方法,但这不是我在这里主要关心的。)
我不明白的是执行中的问题:
ls -l "two three_DD_FF"
尽管有双引号,上面的行仍然会导致搜索 two 文件;而命令提示符上的 same 行则按预期完成工作(即搜索文件“two three_DD_FF"
:
$ ls -l "two three_DD_FF"
-rw-rw-r-- 1 myhome me 0 Aug 27 13:09 'two three_DD_FF'
也就是说,行
echo ${trio}
显示了正确的命令(至少在命令行上执行时;而相同的命令在脚本内执行时会失败。它无法遵守文件名的双引号被搜查。
我的问题:
我的建议:使用数组:
#!/usr/bin/env bash
cmd=(ls -l)
trio=( "${cmd[@]}" "${1}_DD_FF" )
"${trio[@]}"
将脚本中的
echo
替换为xxd <<< ${trio}
,我们可以看到:
00000000: 6c73 202d 6c20 2274 776f 2074 6872 6565 ls -l "two three
00000010: 5f44 445f 4646 220a _DD_FF".
您的变量
trio
因此包含字符串 ls -l "two three_DD_FF"
。
当您运行
${trio}
(可以更简单地写为 $trio
)时,bash 对字符串应用分词,给出以下单词:
0: `ls`
1: `-l`
2: "two
3: three_DD_FF"
因此,使用选项参数 (
ls
) 和两个附加参数 -l
和 "two
来调用 three_DD_FF"
。
这反映在关于找不到
"two
和 three_DD_FF"
的错误消息中。