Significato di ” (parentesi quadre)

Non sono riuscito a trovare nessuna semplice risorsa semplice che spiegasse il significato e la correzione del seguente errore della shell di BASH, quindi sto postando ciò che ho trovato dopo averlo fatto.

L’errore:

-bash: [: too many arguments 

Versione per Google: bash open square bracket colon too many arguments .

Contesto: una condizione if in parentesi quadre singole con un operatore di confronto semplice uguale a, maggiore di ecc., Ad esempio:

 VARIABLE=$(/some/command); if [ $VARIABLE == 0 ]; then # some action fi 

Se il tuo $VARIABLE è una stringa contenente spazi o altri caratteri speciali, e vengono usate parentesi quadre (che è una scorciatoia per il comando test ), allora la stringa può essere divisa in più parole. Ognuno di questi viene trattato come argomento separato.

In modo che una variabile è divisa in molti argomenti :

 VARIABLE=$(/some/command); # returns "hello world" if [ $VARIABLE == 0 ]; then # fails as if you wrote: # if [ hello world == 0 ] fi 

Lo stesso vale per qualsiasi chiamata di funzione che mette giù una stringa contenente spazi o altri caratteri speciali.


Difficoltà facile

Avvolgi l’output variabile tra virgolette, forzandolo a rimanere come una stringa (quindi un argomento). Per esempio,

 VARIABLE=$(/some/command); if [ "$VARIABLE" == 0 ]; then # some action fi 

Semplice come quella. Ma salta a “Attenti anche a …” di seguito se non puoi garantire che la tua variabile non sarà una stringa vuota, o una stringa che non contiene nient’altro che spazi vuoti.


Oppure, una soluzione alternativa consiste nell’utilizzare doppie parentesi quadre (che è una scorciatoia per il new test comando di new test ).

Questo esiste solo in bash (e apparentemente korn e zsh) comunque, e quindi potrebbe non essere compatibile con shell predefinite chiamate da /bin/sh ecc. Ciò significa che su alcuni sistemi, ad esempio, potrebbe funzionare dalla console ma non da cron , a seconda di come è configurato tutto.

Sarebbe come questo:

 VARIABLE=$(/some/command); if [[ $VARIABLE == 0 ]]; then # some action fi 

Fare attenzione anche al [: unary operator expected errore [: unary operator expected

Se visualizzi l’errore “troppi argomenti”, è probabile che stai ricevendo una stringa da una funzione con output imprevedibile. Se è anche ansible ottenere una stringa vuota (o tutta la stringa di spazi vuoti ), questo sarebbe trattato come argomento zero anche con la “correzione rapida” sopra, e fallirebbe con [: unary operator expected

È lo stesso “gotcha” se sei abituato ad altri linguaggi – non ti aspetti che il contenuto di una variabile venga effettivamente stampato nel codice come questo prima che venga valutato.

Ecco un esempio che impedisce sia [: too many arguments e [: unary operator expected errore [: unary operator expected : sostituisce l’output con un valore predefinito se è vuoto (in questo esempio, 0 ), con doppi apici avvolti attorno all’intera cosa:

 VARIABLE=$(/some/command); if [ "${VARIABLE:-0}" == 0 ]; then # some action fi 

(qui, l’azione si verifica se $ VARIABLE è 0 o vuoto. Ovviamente, è necessario modificare lo 0 (il valore predefinito) su un valore predefinito diverso se si desidera un comportamento diverso)


Nota finale: poiché [ è una scorciatoia per il test , tutto questo vale anche per il test: too many arguments errore test: too many arguments (e anche test: unary operator expected )

È appena entrato in questo post, ottenendo lo stesso errore, cercando di verificare se due variabili sono entrambe vuote (o non vuote). Questo risulta essere un confronto composto – 7.3. Altri operatori di confronto – Guida avanzata di scripting di Bash ; e ho pensato che dovrei notare quanto segue:

  • Ho usato -e pensavo significasse “vuoto” all’inizio; ma ciò significa “esiste un file” – usa -z per verificare la variabile vuota (stringa)
  • Le variabili stringa devono essere citate
  • Per il confronto AND logico composto, o:
    • usa due test e && them: [ ... ] && [ ... ]
    • oppure utilizzare l’operatore -a in un singolo test : [ ... -a ... ]

Ecco un comando di lavoro (cercare tutti i file txt in una directory e scaricare quelli trovati in grep contenenti entrambe le parole):

 find /usr/share/doc -name '*.txt' | while read file; do \ a1=$(grep -H "description" $file); \ a2=$(grep -H "changes" $file); \ [ ! -z "$a1" -a ! -z "$a2" ] && echo -e "$a1 \n $a2" ; \ done 

modifica 12 agosto 2013: nota relativa al problema:

si noti che quando si controlla l’uguaglianza delle stringhe con il test classico (single square bracket [ ), si DEVE avere uno spazio tra l’operatore “is equal”, che in questo caso è un singe “equals” = sign (anche se due segni di uguale == sembrano essere accettato anche come operatore per la parità). Quindi, questo fallisce (silenziosamente):

 $ if [ "1"=="" ] ; then echo A; else echo B; fi A $ if [ "1"="" ] ; then echo A; else echo B; fi A $ if [ "1"="" ] && [ "1"="1" ] ; then echo A; else echo B; fi A $ if [ "1"=="" ] && [ "1"=="1" ] ; then echo A; else echo B; fi A 

… ma aggiungi lo spazio – e tutto sembra a posto:

 $ if [ "1" = "" ] ; then echo A; else echo B; fi B $ if [ "1" == "" ] ; then echo A; else echo B; fi B $ if [ "1" = "" -a "1" = "1" ] ; then echo A; else echo B; fi B $ if [ "1" == "" -a "1" == "1" ] ; then echo A; else echo B; fi B 

Ho avuto lo stesso problema con i miei script. Ma quando ho fatto alcune modifiche ha funzionato per me. Mi è piaciuto così: –

 export k=$(date "+%k"); if [ $k -ge 16 ] then exit 0; else echo "good job for nothing"; fi; 

in quel modo ho risolto il mio problema. Spero che possa aiutarti anche per te.

Alcune volte Se si tocca la tastiera accidentalmente e si rimuove uno spazio.

 if [ "$myvar" = "something"]; then do something fi 

Attiverà questo messaggio di errore. Non è richiesto lo spazio prima di ‘]’.