Wie überprüfe ich, ob $ 1 und $ 2 null sind?

40

Ich führe ein Skript aus, das das Zeichenfolgenargument übergibt, und ich möchte tun, wenn sonst die folgende Anweisung angezeigt wird:

if [ $1 != '' ] && [ $2 != '' ]
then 
    do something.....

aber es zeigte sich Error too many argument. Warum?

Taymindis Woon
quelle
Sie sollten 1. den Befehl, den Sie das Skript aufrufen, und 2. die vollständige Ausgabe bereitstellen.
Lucio
2
Sie sollten verwenden [[ ]]. Andernfalls müssen Sie Ihre Variablen angeben.
Christophe De Troyer
Wenn $ 1 nicht existiert, wird $ 2 zu $ ​​1, was den Test von $ 1 und $ 2, die beide null sind, irrelevant erscheinen lässt.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Nicht unbedingt irrelevant - in einigen Fällen möchten Sie sicherstellen, dass Argumente tatsächlich etwas anstelle von Leerzeichen oder Nullzeichen enthalten. $1könnte vom Benutzer des Skripts deaktiviert oder auf null gesetzt werden. Betrachten Sie diese Befehlsfolge: $ set '' bardann werden echo "x${1}x";beide Variablen gesetzt, aber eine von ihnen ist null.
Sergiy Kolodyazhnyy

Antworten:

55

Versuchen Sie es mit dem -z-Test:

if [ -z "$1" ] && [ -z "$2" ]

Vom Menschen bash:

-z string
   True if the length of string is zero.
Sylvain Pineau
quelle
Für mich geht das!
Pengisgood
Es ist interessant, dass die am häufigsten gestellte und akzeptierte Antwort die gestellte Frage nicht wirklich beantwortet.
Mehmet
Beim Schreiben von portablen Shell-Skripten sollte dieses Flag mit Vorsicht verwendet werden, da es auf bestimmten kommerziellen Unixen fehlerhaft ist. Siehe meine Antwort für verknüpfte Quellen.
Sergiy Kolodyazhnyy
14

Da dies markiert ist bash, empfehle ich, das erweiterte Testkonstrukt ( [[...]]) zu verwenden und die Anführungszeichen zu vergessen:

if [[ -z $1 && -z $2 ]]; then
...

Sofern Sie nicht auf sh/ POSIX-Kompatibilität aus sind, gibt es keinen Grund, diese nicht zu verwenden [[ ]].

muru
quelle
3

Folgendes funktioniert auch,

if [ "$1" == "" && "$2" == ""]; then
    echo NULL
fi
Avinash Raj
quelle
Das &&und andere Trennzeichen für logische Befehle sind im Klassiker nicht zulässig test. Sie müssen stattdessen andere Testkonstrukte verwenden (wie -aich denke)
muru
3

Die alte Version der Antwort finden Sie im zweiten Teil dieser Antwort. Wenn Sie Einzelheiten erfahren möchten, lesen Sie weiter

Die Ursache des Problems

In der Frage selbst wird berichtet, dass OP sieht too many arguments error, was beim Testen bashnicht der Fall zu sein scheint:

$ [ $1 != '' ] && [ $2 != '' ]
bash: [: !=: unary operator expected

Mit /bin/shdem Symlink tatsächlich /bin/dashauf Ubuntu, berichteten Fehler wie folgt:

$ sh
$ [ $1 != '' ] && [ $2 != '' ]
sh: 1: [: !=: unexpected operator

Und der Standalone /bin/testauch:

$ /usr/bin/test $1 != ''  
/usr/bin/test: missing argument after ‘’

Anmerkung: Wenn Sie sich fragen, was ist /usr/bin/testund warum ich bashund verwende sh, sollten Sie wissen, dass dies [ein Alias ​​für den testBefehl ist, der auch als eigenständige ausführbare Datei oder häufiger vorhanden ist - als integrierte Shell, die von jeder Shell zuerst verwendet wird . Wie für ifAussagen, arbeiten sie an der Ausfahrt Statuen von Befehlen, also warum [und testsind Befehle, mit allem anderen sind Argumente , die Befehle - falsche Reihenfolge dieser Befehlszeilen args führt zu Fehlern.

Zurück zum Thema: Es ist unklar, wie OP zu dem Fehler kam, der nicht damit zusammenhängt. In allen drei Fällen ist das Problem jedoch dasselbe - nicht festgelegte Variablen werden als leer behandelt, was die Shell also mit diesen nicht angegebenen Variablen sieht

[ != '' ]

das bricht die Syntax, die testversteht. Erinnern Sie sich, was ich über die falsche Reihenfolge der Befehlszeilenargumente gesagt habe? Daher ist das Zitieren wichtig. Lassen Sie uns die Diagnoseausgabe aktivieren und sehen, was die Shell ausführt:

$ set -x
# throws error
$ [ $1 != '' ] && [ $2 != '' ] 
+ '[' '!=' '' ']'
bash: [: !=: unary operator expected
# no error
$ [ "$1" != '' ] && [ "$2" != '' ] || echo null vars
+ '[' '' '!=' '' ']'
+ echo null vars
null vars

Besserer Weg, um nicht gesetzte Variablen zu testen

Ein sehr häufiger Ansatz, den Sie sehen, ist folgender:

 if [ "x$var1" == "x"  ] && [ "x$var2" == "x"  ];                                                                
 then
     echo "both variables are null"
 fi

Um Gilles zu zitieren :

In ["x $ 1" = "x"] stellt das x-Präfix sicher, dass x "$ 1" möglicherweise nicht wie ein Operator aussehen kann. Die Shell kann diesen Test also nur analysieren, indem sie = als binären Operator behandelt.

Vermutlich sollte dies ziemlich portabel sein, da ich diese in /bin/shSkripten gesehen habe. Es kann auch wie in kombiniert werden

if [ "x${var1}${var2}" == "x" ]; then
    ...
fi

Natürlich könnten wir die -zFlagge benutzen , aber laut Recherchen in einigen Shells, insbesondere ksh88 (laut Stephane Chazelas ), ist diese Flagge fehlerhaft.

Siehe auch

Sergiy Kolodyazhnyy
quelle
+1 für einen sehr interessanten Ansatz.
WinEunuuchs2Unix
@ WinEunuuchs2Unix Bearbeitet, um es noch interessanter zu machen :)
Sergiy Kolodyazhnyy
1

Ich denke, der Titel des Beitrags ist nicht korrekt, da die Absicht in der Nachricht war, zu überprüfen, ob $ 1 und $ 2 nicht null sind. Im angegebenen Beispiel fehlten lediglich doppelte Anführungszeichen in $ 1 und $ 2, um zu funktionieren. Variablen müssen in doppelte Anführungszeichen gesetzt werden, um beim Vergleichen von Zeichenfolgen erweitert zu werden. Aber zu prüfen, ob $ 1 und $ 2 existieren, ist dasselbe wie zu prüfen, ob $ 2 existieren, da es nicht existieren kann, wenn $ 1 nicht existiert. Der Befehl 'if' wird auch in diesem Fall nicht benötigt, da 'test' true / false zurückgibt und '&&' als 'then' verwendet, wenn return 0 / true ist:

[ "$2" != '' ] && commands...

Einfacher mit -n (ungleich Null):

[ -n "$2" ] && commands...

Das Überprüfen, ob $ 1 und $ 2 null sind, entspricht dem Überprüfen, ob kein Parameter vorhanden ist:

[ $# -eq 0 ] && commands...
Guariba Som
quelle