![如何使用带空格的字符串插值在 bash 脚本中按程序生成命令?](https://linux22.com/image/160656/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E5%B8%A6%E7%A9%BA%E6%A0%BC%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%8F%92%E5%80%BC%E5%9C%A8%20bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%8C%89%E7%A8%8B%E5%BA%8F%E7%94%9F%E6%88%90%E5%91%BD%E4%BB%A4%EF%BC%9F.png)
我正在尝试创建一个简单的脚本,该脚本使用如下所示的月份列表:
(一月二月)
要生成并执行此命令:
python ExpenseManager.py -p 输入/Jan\ 2019\ Debit.CSV 输入/Jan\ 2019\ Credit.CSV -p 输入/Feb\ 2019\ Debit.CSV 输入/Feb\ 2019\ Credit.CSV
这是我为此编写的程序:
#!/usr/bin/env bash
clear
months=(Jan Feb)
args=()
for month in ${months[@]}; do
args=(${args[@]} -p "Inputs/${month}\\ 2019\\ Debit.CSV" "Inputs/${month}\\ 2019\\ Credit.CSV")
done
python ExpenseManager.py "${args[@]}"
exit 0
从理论上讲,这是有效的。当我回显结果命令时,我得到了我想要的确切命令:
python ExpenseManager.py -p 输入/Jan\ 2019\ Debit.CSV 输入/Jan\ 2019\ Credit.CSV -p 输入/Feb\ 2019\ Debit.CSV 输入/Feb\ 2019\ Credit.CSV
现在,当我复制/粘贴该程序创建的命令并执行它时,它工作正常。然而,当我让 Bash 执行该命令时,它包含了我用来在 Bash 中包含转义反斜杠的反斜杠:
命名空间(filepairs=[['输入/一月\', '2019\', '借记.CSV', '输入/一月\', '2019\', '信用.CSV'], ['输入/二月\ 2019 \ Debit.CSV', '输入/2019 年 2 月\ Credit.CSV']]
我尝试了几种解决方案来使其发挥作用:
我尝试将参数设为单个字符串并以此为基础进行构建
我尝试用单引号将参数括起来,并在空格周围使用双引号,如下所示:
args=(${args[@]} -p '输入/${月}" "2019" "Debit.CSV "输入/${月}" "2019" "Credit.CSV")
- 我尝试使用引号分隔 arg 中需要空格的每个部分,如下所示:
args=(${args[@]} -p "Inputs/${month}" "2019" "Debit.CSV" "Inputs/${month}\ 2019\ Credit.CSV")
我在这里和其他地方查看了其他解决方案,但似乎没有任何效果。因此,我不想继续陷入这个困境,而是希望有人能告诉我让 Bash 执行这个按程序构建的插值命令的魔术?
答案1
不要用来echo
查看正在执行什么命令。它打印命令后解析,即在应用引号和转义之后并删除);因此,如果 的输出echo
包含引号和/或转义符,就像您期望在原始命令行中看到的那样(即在解析之前),则表明存在严重错误。比较这两个命令的输出echo
:
$ month=Jan
$ var="Inputs/${month}\\ 2019\\ Debit.CSV"
$ echo $var
Inputs/Jan\ 2019\ Debit.CSV
$ echo Inputs/Jan\ 2019\ Debit.CSV
Inputs/Jan 2019 Debit.CSV
首先,打印转义符,表明它们不是解析、应用和删除。在第二个例子中,他们消失了,表明他们是解析、应用和删除。
那么,如何解决呢?两条规则:1) 不要在变量中添加引号或转义符(除非在奇怪的情况下字符串将经过额外级别的解析),2) 相反,请在所有变量引用周围添加双引号(包括${args[@]}
) (再说一遍,有一些奇怪的例外)。另外,您可以使用 来添加到数组中array+=("new" "elements")
。
这是固定脚本:
#!/usr/bin/env bash
clear
months=(Jan Feb)
args=()
for month in "${months[@]}"; do
args+=(-p "Inputs/${month} 2019 Debit.CSV" "Inputs/${month} 2019 Credit.CSV")
done
python ExpenseManager.py "${args[@]}"
exit 0