Sens de "[: trop d'arguments" erreur de si [] (crochets)

Je n'ai pas pu trouver une seule ressource simple expliquant la signification et la correction de L'erreur BASH shell suivante, donc je poste ce que j'ai trouvé après la recherche.

l'erreur:

-bash: [: too many arguments

Google-friendly version: bash open square bracket colon too many arguments .

Contexte: si l'état de simples crochets avec une simple comparaison opérateur comme égal, supérieur à etc, par exemple:

VARIABLE=$(/some/command);
if [ $VARIABLE == 0 ]; then
  # some action
fi 
140
demandé sur user568458 2012-12-08 23:46:25

4 réponses

si votre $VARIABLE est une chaîne contenant des espaces ou d'autres caractères spéciaux, et que des crochets simples sont utilisés (qui est un raccourci pour la commande test ), alors la chaîne peut être divisée en plusieurs mots. Chacun d'eux est traité comme un argument distinct.

de sorte que une variable est divisée en plusieurs arguments :

VARIABLE=$(/some/command);  
# returns "hello world"

if [ $VARIABLE == 0 ]; then
  # fails as if you wrote:
  # if [ hello world == 0 ]
fi 

il en sera de même pour tout appel de fonction qui dépose une chaîne contenant des espaces ou d'autres caractères spéciaux.


Easy fix

envelopper la sortie variable en guillemets doubles, le forçant à rester comme une chaîne de caractères (donc un argument). Par exemple,

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

aussi Simple que cela. mais Sauter à " attention aussi..."ci-dessous si vous ne pouvez pas garantir que votre variable ne sera pas une chaîne vide, ou une chaîne qui ne contient que de l'espace blanc.


Ou, une de autre solution", 1519240920" consiste à utiliser des doubles crochets (qui est un raccourci pour "151960920 de la commande").

cela n'existe qu'en bash (et apparemment korn et zsh) cependant, et peut donc ne pas être compatible avec les shells par défaut appelés par /bin/sh etc. Cela signifie que sur certains systèmes, par exemple, il peut travailler à partir de la console, mais pas de cron , selon la configuration.

il ressemblerait à ceci:

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

attention aussi à l '"erreur 151990920

si vous voyez l'erreur" trop d'arguments", il y a des chances que vous obteniez une chaîne d'une fonction avec une sortie imprévisible. S'il est aussi possible d'obtenir une chaîne vide (ou toute chaîne à espace blanc), ce serait traité comme des arguments zéro, même avec le "quick fix" ci-dessus, et échouerait avec [: unary operator expected

c'est le même 'gotcha' si vous êtes habitué à d'autres langues - vous ne vous attendez pas à ce que le contenu d'une variable soit effectivement imprimé dans le code avant qu'il ne soit évalué.

voici un exemple qui prévient à la fois les erreurs [: too many arguments et [: unary operator expected : remplacer la sortie par une valeur par défaut si elle est vide (dans cet exemple, 0 ), avec des guillemets enroulés autour du tout:

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

(ici, l'action aura lieu si $VARIABLE est 0, ou vide. Naturellement, vous devez changer le 0 (la valeur par défaut) à une valeur par défaut différente si un comportement différent est voulu)


note finale: puisque [ est un raccourci pour test , tout ce qui précède est aussi vrai pour l'erreur test: too many arguments (et aussi test: unary operator expected )

261
répondu user568458 2017-07-11 18:53:29

vient de heurter ce poteau, en obtenant la même erreur, en essayant de tester si deux variables sont les deux vide (ou non vide). Il s'avère que c'est un comparaison composé - 7.3. Autres opérateurs de comparaison-Bash avancé - Guide de script ; et j'ai pensé que je devrais noter ce qui suit:

  • j'ai utilisé -e en pensant que cela signifie "vide" au début; mais cela signifie " fichier existe" - utiliser -z pour tester vide variable (chaîne)
  • les variables de chaîne doivent être citées
  • pour la logique composée et la comparaison, soit:
    • utilisez deux test s et && them: [ ... ] && [ ... ]
    • ou utilisez l'opérateur -a en un seul test : [ ... -a ... ]

voici un commande de travail (recherche à travers tous les fichiers txt dans un répertoire, et dumping ceux que grep trouve contiennent deux mots):

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

modifier le 12 août 2013: problème lié à la remarque:

notez que lors de la vérification de l'égalité de la chaîne avec le classique test (simple crochet carré [ ), vous doit avoir un espace entre l'opérateur "est égal", qui dans ce cas est un simple le signe" égale " = (bien que deux signes égaux == semblent également acceptés comme opérateurs d'égalité). Ainsi, cela échoue (silencieusement):

$ 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

... mais ajoutez l'espace - et tout semble bon:

$ 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
9
répondu sdaau 2013-08-12 07:37:50

j'ai eu le même problème avec mes scripts. Mais quand j'ai fait quelques modifications, ça a marché pour moi. J'ai fait comme ceci :-

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

comme ça j'ai résolu mon problème. Espère que cela va vous aider trop.

1
répondu Kidane 2017-06-17 16:24:43

parfois si vous touchez accidentellement le clavier et retirez un espace.

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

va déclencher ce message d'erreur. Pas d'espace avant ']' est nécessaire.

0
répondu Kemin Zhou 2018-06-07 16:47:18