如何使用帶空格的字元串插值在 bash 腳本中程序生成命令?
我正在嘗試創建一個簡單的腳本,它使用這樣的月份列表:
(一月二月)
要生成並執行此命令:
python ExpenseManager.py -p Inputs/Jan\ 2019\ Debit.CSV Inputs/Jan\ 2019\ Credit.CSV -p Inputs/Feb\ 2019\ Debit.CSV Inputs/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 Inputs/Jan\ 2019\ Debit.CSV Inputs/Jan\ 2019\ Credit.CSV -p Inputs/Feb\ 2019\ Debit.CSV Inputs/Feb\ 2019\ Credit.CSV
現在,當我複制/粘貼該程序創建的命令並執行它時,它工作正常。但是,當我讓 Bash 執行命令時,它包含了我用來在 Bash 中包含轉義反斜杠的反斜杠:
命名空間(文件對=
$$ [‘Inputs/Jan', ‘2019', ‘Debit.CSV’, ‘Inputs/Jan', ‘2019', ‘Credit.CSV’ $$,$$ ‘Inputs/Feb\ 2019
Debit.CSV’, ‘Inputs/Feb\ 2019\ Credit.CSV’ $$]我已經嘗試了幾種解決方案來讓它工作:
- 我嘗試將 args 設為單個字元串並以此為基礎
- 我試過用單引號將 args 括起來,並在空格周圍使用雙引號,如下所示:
參數=( $ {args[@]} -p ‘Inputs/ $ {month}" “2019” “Debit.CSV “Inputs/${month}” “2019” “Credit.CSV”)
- 我嘗試使用這樣的引號分隔需要空格的 arg 的每個部分:
args=(${args[@]} -p "Inputs/${month}" "2019" "Debit.CSV" "Inputs/${month}\ 2019\ Credit.CSV")
我在這里和其他地方查看了其他解決方案,但似乎沒有任何效果。因此,與其繼續停留在這個問題上,我希望有人能告訴我讓 Bash 執行這個程序建構的內插命令的魔術嗎?
不要
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