$(命令替換)內的環境變數擴展
我在 Debian 上執行 Bash 5.1.4。
我正在編寫一個安裝後腳本來將配置和其他文件複製到我的主目錄中的位置。我在每個文件的開頭添加了預期的目的地,並帶有前綴;例如:(
# DEST: $HOME/.config/mousepad/Thunar
當然,在腳本中,文件名將替換為變數,井號由適當的註釋字元替換;這一行出現在前 10 行中,不一定在第一行,所以我不與shebangs混淆)。為了獲得這些位置,我使用了這個命令:
head Thunar.acs | egrep "DEST:" | awk '{print $3}
,它按字面意思返回$HOME/.config/Thunar
;我希望它擴大$HOME
。我的意思是當我嘗試時ls $(head Thunar.acs | egrep "DEST:" | awk '{print $2})
我得到了錯誤ls: cannot access '$HOME/.config/Thunar/': No such file or directory
。我閱讀了這個問題並嘗試了所選答案中的所有雙引號組合,但仍然出現錯誤。我該如何解決這個問題?將變數名括在大括號中也不起作用。
謝謝!
命令替換和變數擴展不是遞歸的。也就是說,當 shell 擴展類似
$varname
or的東西時$(somecommand)
,它不會掃描結果以查找要擴展的$varname
or的其他實例。$(somecommand)
它對結果所做的唯一一件事就是嘗試將其拆分為“單詞”並擴展任何看起來像文件名萬用字元的內容;這些造成的麻煩比其他任何事情都多,因此您幾乎應該總是雙引號引用副檔名,這樣就可以不用管它了。如果您確實想
$HOME
擴展到實際的主路徑,我看到的最簡單的方法是將它通過管道envsubst
(這將擴展任何看起來像環境變數引用的東西,但請注意它僅適用於環境變數,而不適用於未導出的 shell 變數),或awk
進行替換(只會執行您告訴它替換的特定變數)。在我展示如何做到這一點之前,我必須反對使用三個工具 –
head
、egrep
和awk
– whenawk
完全有能力完成整個工作本身:awk '/DEST:/ {print $3}; (NR>=10) {exit}' Thunar.acs
該
/DEST:/
位egrep
在原始文件中完成了工作,並(NR>=10) {exit}
替換了head -n 10
.所以,這是一個使用的版本
envsubst
:ls "$(awk '/DEST:/ {print $3}; (NR>=10) {exit}' Thunar.acs | envsubst)"
(注意雙引號以防止分詞和萬用字元擴展做任何奇怪的事情。)
這是一個使用
awk
’ssub
函式進行替換的版本:ls "$(awk -v home="$HOME" '/DEST:/ {sub("\\$HOME",home,$3); print $3}; (NR>=10) {exit}' Thunar.acs)"