2016-02-23 85 views
4

這不是一個真正的問題(儘管我最後有一個),而是解決我想分享的問題的一個解決方案,以幫助其他人。bash [:太多的參數大於符號

打開一個新終端(特別是安裝了bash完成macport的OS X上的iTerm2)時,我得到的最長時間是bash: [: too many arguments。該錯誤起源於文件/opt/local/etc/bash_completion中的線if [ -n "$BASH_VERSION" -a -n "$PS1" -a -z "$BASH_COMPLETION_COMPAT_DIR" ]; then。我終於找到了我的.bash_profile中有export PS1='>'這個事實。將PS1更改爲其他內容(例如'> ')解決了bash完成時的問題。

在OS X和Debian一些實驗表明,添加額外的表達式(具有-a-o)插入涉及'>'中表達後的測試([ ])時,會發生該問題。例如,

> A='>'; if [ -n "$A" ]; then echo "yes"; fi 
yes 
> A='>'; if [ -n "$A" -a -n "$A" ]; then echo "yes"; fi 
bash: [: too many arguments 
> A='> '; if [ -n "$A" -o -n "$A" ]; then echo "yes"; fi 
yes 
> A='>'; if [ -n "$A" -o -n "Hello" ]; then echo "yes"; fi 
bash: [: too many arguments 
> A='>'; if [ -n "Hello" -a -n "$A" ]; then echo "yes"; fi 
yes 

這是一個(已知)在bash中的錯誤?

+0

我認爲這是由於「大於」運算符優先於'-n'運算符 – edi9999

+3

而不是使用新的'[[]]'的另一個原因。 – 123

+0

@ edi9999當然,「大於」應該被解釋爲只是一個字符串?畢竟,它使用'>>''。 (這就是爲什麼我想知道這是否是一個bug。) @ 123是的,我通常會使用'[[]]',但這是在我沒有寫的腳本中(即'bash_completion'),而我只控制'PS1'環境變量。 –

回答

4

你的解決方法是有效的,只要存儲在$A字符串不是操作[/test識別 - 簡單地增加一個空間就足夠了,因爲你已經發現。

當然,「大於」應該被解釋爲只是一個字符串?畢竟它與'>'一起工作。

不,$A內容解釋爲只是一個字符串。 (如果你想,你不得不使用[[代替,這是在一個特殊的背景下分析,更像是你從傳統的編程語言的期望。)

[test)是一個內嵌(也存在如 - $A引用被替換的變量在此情況下,內容

  • 殼執行其擴展第一:因此在大多數系統的外部實用程序),並與命令語法,這意味着解析。然後
  • 結果傳遞到[

因此,從[的角度看,這並不重要手術者是否它最終看到 - >在你的榜樣 - 來自一個字面或存儲在變量中。

但是請注意,空格問題:通過>(空格)被解釋爲運算符; >,相反,><space>不是 - 因爲確切的文字是更多而不僅僅是運營商。


的底線是:

  • 你使用bash的完成腳本不穩健
  • 正如關於這個問題的評論@chepner狀態,POSIX recommends not using -o/-a避免你遇到的不確定性(重點煤礦):

的XSI擴展指定-a和-o二進制初選和'('和')'操作員被標記爲過時。 (使用它們許多表達式含糊通過根據被評估的特定表達式語法定義。)

  • 具體地,使用單獨的[ ... ]表達與&&(而不是-a)和||(而不是連接-o)解決了這個問題:

    [ -n "$BASH_VERSION" ] && [ -n "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ] 
    

或者更簡單地說,採取非空字符串的優勢評估爲true:

[ "$BASH_VERSION" ] && [ "$PS1" ] && [ -z "$BASH_COMPLETION_COMPAT_DIR" ] 

注意的是,雖然-a-o介紹歧義,他們一個安全問題 - 你不能通過它們的使用注入任意代碼。

+0

好的,就像@chepner上面說的那樣,這是完成腳本中比Bash本身更多的錯誤。我將這個答案標記爲正確的,然後解釋爲什麼我給出的解決方法是正確的。還有一個問題:是否有可能在這裏惡意使用$ A的擴展,還是隻會導致某種解析錯誤? –

+0

@BrettRyland:請參閱我的更新。 – mklement0

+1

好,很好。感謝您的額外澄清! –

2

如果要使用兩個或兩個以上的條件,你應該使用

if [ condition1 ] && [condition2 ] 

if [ condition1 ] || [condition2 ] 

所以你的情況(第一,如果 「和」):

A='>'; if [ -n "$A" ] && [ -n "$A" ]; then echo "yes"; fi 

對於「或」如果:

A='>'; if [ -n "$A" ] || [ -n "Hello" ]; then echo "yes"; fi 

但請注意,第二次檢查[ -n "Hello" ]始終爲真,因此最好將其刪除。

你可能會對shellcheck感興趣,以驗證你的bash腳本語法。

+1

首先,http://wiki.bash-hackers.org/commands/classictest#misc_syntax將'-a'和'-o'語法記錄爲用於組合測試表達式的適當方法,並且它們在現有的bash腳本中被廣泛使用(因此我的問題與bash完成)。其次,'-n「你好」「只是一個簡單的總是真實的表達,我用它來證明我的觀點。我實際上不會使用像這樣的表達式來實現任何有用的功能! :-P –

+0

@BrettRyland是的,你說得對--a和-o,但我只是想找到一個替代和快速解決你的問題。 ;)順便說一句我已經用-a和-o選項更新了答案 – ClaudioM

+1

'[...] -o [...]''顯然是錯誤的;除去。順便說一句,'[-n「>」]'很好,因爲'test'在* *兩個*參數的第二個(忽略強制性參數)時認識到'>'不是一個操作符。 – chepner