Betekenis van de fout “[: te veel argumenten” van if [] (vierkante haken)

Ik kon geen enkele eenvoudige, duidelijke bron vinden die de betekenis van en de oplossing voor de volgende BASH-shellfout beschrijft, dus plaats ik wat ik heb gevonden na onderzoek.

De fout:

-bash: [: too many arguments

Google-vriendelijke versie:bash open square bracket colon too many arguments.

Context:een if-voorwaarde tussen enkele vierkante haken met een eenvoudige vergelijkingsoperator zoals is gelijk aan, groter dan enz., bijvoorbeeld:

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

Antwoord 1, autoriteit 100%

Als uw $VARIABLEeen tekenreeks is met spaties of andere speciale tekens, en enkele vierkante haken worden gebruikt(wat een snelkoppeling is voor de opdracht test), dan kan de tekenreeks worden gesplitst uit in meerdere woorden. Elk van deze wordt behandeld als een afzonderlijk argument.

Zodat één variabele wordt opgesplitst in meerdere argumenten:

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

Hetzelfde geldt voor elke functieaanroep die een tekenreeks invoert die spaties of andere speciale tekens bevat.


Eenvoudige oplossing

Wikkel de uitvoer van de variabele tussen dubbele aanhalingstekens en dwing het om als één string te blijven (dus één argument). Bijvoorbeeld,

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

Zo simpel is het.Maar ga naar “Ook oppassen…” hieronder als u ook niet kunt garanderen dat uw variabele geen lege tekenreeks is, of een tekenreeks die niets anders dan witruimte bevat .


Of een alternatieve oplossingis het gebruik van dubbele vierkante haken (wat een snelkoppeling is voor de opdracht new test).

Dit bestaat echter alleen in bash (en blijkbaar korn en zsh), en is dus mogelijk niet compatibel met standaardshells die worden aangeroepen door /bin/shenz.

Dit betekent dat op sommige systemen het mogelijk werkt vanaf de console, maar niet wanneer het ergens anders wordt aangeroepen, zoals vanuit cron, afhankelijk van hoe alles is geconfigureerd.

Het zou er zo uitzien:

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

Als je opdracht dubbele vierkante haken zoals deze bevat en je krijgt fouten in logbestanden, maar het werkt vanaf de console, probeer dan de [[] uit te wisselen voor een alternatief dat hier wordt voorgesteld, of zorg ervoor dat wat er ook wordt uitgevoerd je script gebruikt een shell die [[oftewel new testondersteunt.


Pas ook op voor de fout [: unary operator expected

Als je de foutmelding ‘te veel argumenten’ ziet, is de kans groot dat je een tekenreeks krijgt van een functie met onvoorspelbare uitvoer. Als het ook mogelijk is om een ​​lege tekenreeks te krijgen(of alle witruimtetekenreeksen), zou dit worden behandeld als nulargumenten, zelfs met de bovenstaande “snelle oplossing”, en zou mislukken met [: unary operator expected

Het is hetzelfde probleem als je andere talen gewend bent – je verwacht niet dat de inhoud van een variabele op deze manier effectief in de code wordt afgedrukt voordat deze wordt geëvalueerd.

Hier is een voorbeeld dat zowel de [: too many argumentsals de [: unary operator expectedfouten voorkomt: de uitvoer vervangen door een standaardwaarde als deze leeg is ( in dit voorbeeld 0), met dubbele aanhalingstekens om het geheel:

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

(hier vindt de actie plaats als $VARIABLE 0 of leeg is. Natuurlijk moet u de 0 (de standaardwaarde) wijzigen in een andere standaardwaarde als ander gedrag gewenst is)


Laatste opmerking:aangezien [een snelkoppeling is voor test, geldt al het bovenstaande ook voor de fout test: too many arguments(en ook test: unary operator expected)


Antwoord 2, autoriteit 4%

Ik kwam zojuist dit bericht tegen, door dezelfde fout te krijgen, terwijl ik probeerde te testen of twee variabelen beideleeg (of niet-leeg) zijn. Dat blijkt een samengestelde vergelijking te zijn – 7.3. Andere vergelijkingsoperators – Advanced Bash-Scripting Guide; en ik dacht dat ik het volgende moet noteren:

  • Ik gebruikte -eomdat ik dacht dat het eerst “leeg” betekende; maar dat betekent “bestand bestaat” – gebruik -zvoor het testen van lege variabele(string)
  • Tekenreeksvariabelen moeten tussen aanhalingstekens staan
  • Voor samengestelde logische EN-vergelijking:
    • gebruik twee testen en &&ze: [ ... ] && [ ... ]
    • of gebruik de operator -ain een enkele test: [ ... -a ... ]

Hier is een werkende opdracht (door alle txt-bestanden in een map zoeken en die waarvan grepvindt dat ze beide van twee woorden bevatten) dumpen:

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

Bewerk 12 aug 2013: gerelateerde probleemopmerking:

Houd er rekening mee dat wanneer u de gelijkheid van tekenreeksen controleert met de klassieke test(enkele vierkante haakjes [), u MOETeen spatie hebben tussen de “is gelijk aan “, wat in dit geval een enkel “gelijk” =-teken is (hoewel twee gelijktekens ==ook als gelijkheidsoperator lijken te worden geaccepteerd). Dit mislukt dus (stil):

$ 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

… maar voeg de spatie toe – en alles ziet er goed uit:

$ 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

Antwoord 3

Een ander scenario waarin u de [: too many argumentsof [: a: binary operator expectedfouten kunt krijgen, is als u probeert te testen op alle argumenten "$@"

if [ -z "$@" ]
then
    echo "Argument required."
fi

Het werkt correct als je foo.shof foo.sh arg1aanroept. Maar als je meerdere argumenten doorgeeft, zoals foo.sh arg1 arg2, krijg je fouten. Dit komt omdat het wordt uitgebreid tot [ -z arg1 arg2 ], wat geen geldige syntaxis is.

De juiste manier om te controleren op het bestaan ​​van argumenten is [ "$#" -eq 0 ]. ($#is het aantal argumenten).


Antwoord 4

Ik had ook hetzelfde probleem. @sdaau antwoord heeft me op een logische manier geholpen. Hier wat ik aan het doen was, wat mij syntactisch correct lijkt, maar ik krijg te veel argumenten fout.

Verkeerde syntaxis:

if [ $Name != '' ] && [ $age != '' ] && [ $sex != '' ] && [ $birthyear != '' ]  && [ $gender != '' ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "Enter all the values"
fi

in bovenstaande if-statement, als ik de waarden van de variabele doorgeef zoals hieronder vermeld, kreeg ik ook een syntaxisfout

export "Name"="John"
export "age"="31"
export "birthyear"="1990"
export "gender"="M"

Met onderstaande syntax krijg ik verwachte output.
Correcte syntaxis:

if [ "$Name" != ""  -a  "$age" != ""  -a  "$sex" != ""  -a  "$birthyear" != ""   -a  "$gender" != "" ] 
then
    echo "$Name"
    echo "$age"
    echo "$sex"
    echo "$birthyear"
    echo "$gender"
else
    echo "it failed"
fi

Er zijn enkele punten waar we rekening mee moeten houden

  1. gebruik “” in plaats van ”
  2. gebruik -a in plaats van &&
  3. plaats een spatie voor en na het operatorteken zoals [ a = b], gebruik niet als [ a=b ] in de if-voorwaarde

Vandaar dat bovenstaande oplossing voor mij werkte !!!


Antwoord 5

Soms als je per ongeluk het toetsenbord aanraakt en een spatie hebt verwijderd.

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

Dit foutbericht wordt geactiveerd. Let op de spatie voor ‘]’ is vereist.


Antwoord 6

Ik heb hetzelfde probleem gehad met mijn scripts. Maar toen ik wat aanpassingen deed, werkte het voor mij. Ik vond dit leuk:-

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

op die manier heb ik mijn probleem opgelost. Ik hoop dat dat ook voor jou zal helpen.

Other episodes