Bash
如何在bash中擴展“單詞”?不談論文件萬用字元
抱歉這麼簡單的問題,但我自己找不到解決方案。
我跑:
$ echo {1..4} 1 2 3 4
這對我來說沒問題。但如果我:
$ echo "{1..4}" > file $ cat file {1..4} $ echo $(<file) {1..4} $ echo $(cat file) {1..4}
我正在尋找一種方法來擴展
{1..4}
文件file
中的字元串echo
,但沒有成功。
我想你正在尋找這個:
eval "echo $(cat file)"
eval 構造一個命令,然後由 shell 執行。
您只是沒有使用正確的工具來完成這項工作:
[user@host dir]$ ksh $ echo "{1..4}" > file $ cat file {1..4} $ echo $(<file) 1 2 3 4 $ echo $(cat file) 1 2 3 4
撇開玩笑不談,Bash 中的擴展順序是:
- 支撐擴展;
- 波浪號擴展、參數和變數擴展、算術擴展和命令替換(以從左到右的方式完成);
- 分詞;
- 和文件名擴展。
因此,在 中,(不帶引號的)命令替換的輸出僅經歷分詞和文件名擴展 - 保持不變,
echo $(cat file)
因為它不包含模式匹配字元(並且假設您的IFS
變數不包含{
、1
、.
或)。4``}
雖然可以嵌套一些擴展,但對於會觸發從階段到目前階段的擴展的字元,通常不會再次解析擴展的結果。(有充分的理由:想想
foo=\$foo; echo "$foo"
)。要將大括號擴展應用於內容,
file
您需要建構一個新命令行並讓 shell 解析並執行它。一種方法是,如您所擁有的其他答案eval
所示。或者,您可以使用程序替換:$ . <(printf '%s ' echo; cat file) 1 2 3 4
請注意,在這兩種情況下,的全部內容都
file
將在目前環境中解析和執行。
bash
同樣,但在新程序的單獨環境中執行:$ bash <<<$( printf "%s " echo; cat file; ) 1 2 3 4
順便說一句,ksh93(我在第一個程式碼塊中使用的 shell)以一種特殊的方式執行:大括號擴展在稍後階段執行,作為欄位拆分的一部分,並且重新解析先前擴展的結果以檢測大括號表達式1:
$ bash -c 'echo {1..$(printf %s 3)}' mybash {1..3} $ ksh -c 'echo {1..$(printf %s 3)}' myksh 1 2 3
1 正如 Stéphane Chazelas在評論中指出的那樣,ksh93 的這種行為可以被視為一個錯誤並且不符合 POSIX,因為它可以
$var
不擴展為var
.