![為什麼 bash 和 zsh 將 [-1] 計算為 1?](https://rvso.com/image/1681636/%E7%82%BA%E4%BB%80%E9%BA%BC%20bash%20%E5%92%8C%20zsh%20%E5%B0%87%20%5B-1%5D%20%E8%A8%88%E7%AE%97%E7%82%BA%201%EF%BC%9F.png)
我注意到這種令人驚訝的行為,但不太明白發生了什麼事:
$ bash -c 'echo [-1]'
1
$ zsh -c 'echo [-1]'
1
看起來命令解析器嘗試計算一個表達式:
$ echo [1,2,3]
1
$ echo [123-33]
1
因為如果表達式被引用,或表示括號只是一個括號,那麼奇怪的評估就會被省略。
$ echo \[123-33]
[123-33]
$ echo [123-33\]
[123-33]
$ echo '[123-33]'
[123-33]
在尋找線索時,我發現了這樣一句話:
注意事項
對 Bash 關聯數組建立索引時,請務必使用引號。否則,靜態解析器將不得不假設索引是算術表達式。
$ echo '${array[spaced string]}' | shfmt 1:16: not a valid arithmetic operator: string $ echo '${array[dash-string]}' | shfmt ${array[dash - string]}
不知道該怎麼做,因為在上下文中沒有數組可言echo [1-1]
這當然可能是由我自己的環境中的某些原因引起的,但當我檢查時,它似乎不是:
$ env -i HOME=$(mktemp -d) bash --noprofile --norc
bash-5.1$ echo [1-1]
1
$ env -i HOME=$(mktemp -d) /bin/bash-4.4 --noprofile --norc
bash-4.4-4.4$ echo [1-1]
1
但話又說回來,在 ubuntu 機器上我得到了不同的結果:
$ bash --version | sed 1q; echo [1-1]
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
[1-1]
停用所有選項不會改變此行為。
for i in `shopt | awk '/on$/ { print $1}'`; do shopt -u $i;done
你知道是什麼導致這個括號表達式被求值以及為什麼結果是 1 嗎?
答案1
1
只有當當前目錄中有一個名為的檔案時才會發生這種情況。
$ bash -c 'echo [-1]'
[-1]
$ touch 1
$ bash -c 'echo [-1]'
1
$ rm 1
$ bash -c 'echo [-1]'
[-1]
為什麼? shell 會對[-1]
名為-
或 的檔案進行比對1
。因此,如果存在具有此類單字元名稱的文件,則 glob 匹配並且您將獲得文件名稱。如果不存在這樣的文件,則 glob 保持不變。
PS:它也適用於-
:
$ touch ./-
$ bash -c 'echo [-1]'
-