Bash

如何在bash中擴展“單詞”?不談論文件萬用字元

  • July 19, 2020

抱歉這麼簡單的問題,但我自己找不到解決方案。

我跑:

$ 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 中的擴展順序是:

  1. 支撐擴展;
  2. 波浪號擴展、參數和變數擴展、算術擴展和命令替換(以從左到右的方式完成);
  3. 分詞;
  4. 和文件名擴展。

因此,在 中,(不帶引號的)命令替換的輸出僅經歷分詞和文件名擴展 - 保持不變,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.

引用自:https://unix.stackexchange.com/questions/598898