me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
,並使用 「\」 轉義符:
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
我明明做一些愚蠢的事。
如何獲得輸出「BAR * BAR」?
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
,並使用 「\」 轉義符:
me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR
我明明做一些愚蠢的事。
如何獲得輸出「BAR * BAR」?
設置$ FOO時引用是不夠的。你需要引用變量的引用,以及:
me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR
echo "$FOO"
這可能是值得進入命令行上使用printf
而不是echo
的習慣。
在這個例子中,它沒有多少好處,但它對於更復雜的輸出可能更有用。
FOO="BAR * BAR"
printf %s "$FOO"
爲什麼在地獄中? printf是一個單獨的進程(至少不是內置的bash),並且使用printf對回顯沒有任何好處。 – ddaa 2008-09-19 14:35:18
printf *是*一個內置的bash,我在我的答案中說過「在這個例子中,它並沒有帶來太多好處,但它對於更復雜的輸出可能更有用。」 – 2008-10-02 10:50:22
簡短的回答
像其他人說的 - 你應該總是引用變量,以防止奇怪的行爲。所以使用echo「$ foo」而不是僅僅echo $ foo。
長的答案
我認爲這個例子值得進一步解釋,因爲有更多的事情比它可能會在它的臉上似乎。
我能看到你的困惑來自於你跑,你可能會想到自己的第一個例子是,外殼顯然做,因爲後:
所以從你的第一個例子:
me$ FOO="BAR * BAR"
me$ echo $FOO
A壓腳提升參數擴展相當於:
me$ echo BAR * BAR
和文件名,擴展後相當於:
me$ echo BAR file1 file2 file3 file4 BAR
如果你只需要輸入echo BAR * BAR
在命令行中,你會發現它們是等價的。
所以你可能認爲自己「如果我逃避*,我可以防止文件名擴展」
所以從你的第二個例子:
me$ FOO="BAR \* BAR"
me$ echo $FOO
參數擴展後應該等於:
me$ echo BAR \* BAR
和文件名,擴展後應該等於:
me$ echo BAR \* BAR
如果您嘗試直接在命令行中鍵入「echo BAR \ * BAR」,它確實會打印「BAR * BAR」,因爲文件名擴展被轉義阻止。
那麼爲什麼使用$ foo不工作?
這是因爲發生了第三次擴展 - 報價清除。從bash的手冊引用的去除是:
前述膨脹後,將字符 「\」,「」」,和「「」未從上述擴展的一個結果 的所有 沒有引用的出現是 刪除。
會發生什麼是當你直接鍵入命令在命令行中,轉義字符不是以前的擴張的結果,從而BASH將其發送到echo命令之前刪除它,但在第二個例子中,「\ *」是以前參數擴展的結果,所以不會被刪除。因此,echo收到「\ *」,這就是它打印的內容。
請注意第一個例子之間的區別 - 「*」不包含在將通過刪除報價去除的字符中。
我希望這是有道理的。最後得出結論 - 只用引號。我只是想我會解釋爲什麼轉義,如果只有參數和文件名擴展在起作用,這在邏輯上應該工作,不起作用。
對於BASH擴展的完整說明,請參閱:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
我會有點添加到這個古老的線程。
通常你會使用
$ echo "$FOO"
不過,我有問題,即使有這樣的語法。考慮下面的腳本。
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
的*
需要被逐字傳遞給curl
,但也會出現同樣的問題。上面的例子將不起作用(它將擴展到當前目錄中的文件名)並且都不會\*
。您也不能引用$curl_opts
,因爲它將被識別爲curl
的單一(無效)選項。
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
因此,我建議使用bash
可變$GLOBIGNORE
的乾脆防止文件名擴展如果施加到全局模式,或使用set -f
內置標誌。
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
應用到你原來的例子:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
這很神祕,這是爲什麼?到底是怎麼回事? – tofutim 2018-03-10 22:38:07