Wozu dient der Bash-Null-Operator „:“ (Doppelpunkt)?

13

Wozu dient der Operator "null" in einem BASH-Skript? Ich verstehe, dass es als Platzhalter nach einem ifBefehl verwendet wird, wenn Sie nichts zu sagen haben, aber einen Befehl benötigen, damit das Programm ordnungsgemäß ausgeführt werden kann. Aber wozu dient es insgesamt? Wann würdest du es benutzen? Wann ist es sinnvoll, es zu benutzen?

Justin
quelle
Lesen Sie auch Verwenden eines
Doppelpunkts
1
Der Grund, den Sie anführen, ist ziemlich wichtig. Warum brauchst du mehr?
Terdon

Antworten:

16

Es ist manchmal nützlich, Nebeneffekte von Parametererweiterungen zuzulassen.

Beispiel: Festlegen eines Standardwerts

read -p "Enter your name: " name
: ${name:=John Doe}  # if the user entered an empty string
echo "$name"
Glenn Jackman
quelle
2
Können Sie symbolweise erklären, wie die zweite Zeile funktioniert?
Ruslan
Weitere Informationen zur :Befehls- und Parametererweiterung finden Sie im bash-Handbuch.
Glenn Jackman
4
Um zu skizzieren, auf was @glennjackman verweist, ruft die zweite Zeile den Befehl null: auf und ${name:="John Doe"}wird erweitert, wodurch die Zuweisung stattfindet, da sie als Argument für Folgendes gelesen wird:. Ohne das: versucht die Shell, "John Doe" als Befehl auszuführen, oder den Wert, $namewenn er bereits festgelegt ist
imkendal
13

Sie können es auch für Endlosschleifen verwenden:

while : ; do 
   # ....
done
Choroba
quelle
4
Aber vielleicht while trueist es besser lesbar, weil (a) weniger Interpunktion verwendet wird und (b) C-abgeleiteten Sprachen ähnlicher ist.
wchargin
9

Sie können damit eine Datei erstellen, ohne ein Programm auszuführen:

: > /path/to/file

Dies ist unendlich viel schneller als touch /path/to/file (da das touchProgramm nicht ausgeführt werden muss) und möglicherweise etwas portabler als nur normal

> /path/to/file

Das scheint auf vielen Systemen zu funktionieren. Auf ähnliche Weise kann überprüft werden, ob Sie Schreibzugriff auf eine Datei haben :

if { : >> /path/to/file;} 2> /dev/null
then
    echo "writeable"
else
    echo "write permission denied"
fi

Dies kann jedoch auch im Allgemeinen ohne das getan werden :. Vorsichtsmaßnahmen:

  • Dies prüft nicht, ob die Datei bereits existiert. Wenn dies nicht der Fall ist, wird die Datei erstellt, sofern sie dazu berechtigt ist.
  • Wenn die Datei nicht vorhanden ist und Ihr Skript keine Berechtigung zum Erstellen hat, wird dies als "Schreibberechtigung verweigert" gemeldet.

(Siehe die verknüpfte Frage aus Gründen, warum dies zuverlässiger ist als if [ -w /path/to/file ].)

G-Man sagt, "Monica wiedereinsetzen"
quelle
5

In früheren Versionen von Unix V6 und Thompson Shell wurde das :tatsächlich als Teil der gotoAnweisung verwendet. Laut Handbuch erschien es ursprünglich in Version 3 von Unix:

Die gesamte Befehlsdatei wird nach einer Zeile durchsucht, die mit einem: als erstem nicht leeren Zeichen beginnt, gefolgt von einem oder mehreren Leerzeichen und dann der Bezeichnung. Wenn eine solche Zeile gefunden wird, wird der Versatz der Befehlsdatei zur Zeile nach dem Label neu positioniert und beendet. Dadurch wird die Shell auf die beschriftete Zeile übertragen.

Heutzutage wird bashes als No-Op-Operator verwendet und kehrt zum Erfolg zurück. In der Tat, wenn Sie sich den Quellcode ansehen , werden Sie sehen, dass beide trueund :dieselbe Funktion int colon_builtin(), darunter, verwenden. Es gibt keinen :nicht eingebauten Befehl und er /bin/trueist eigentlich ein ziemlich großer Befehl für das, was er tut.

:könnte überall trueverwendet werden, zum Beispiel in command_that_can_fail || true, obwohl dies Nicht-Experten verwirren dürfte. Lesen Sie hier mehr darüber .

Sergiy Kolodyazhnyy
quelle
3

Sie können es für den positiven Test eines ifBefehls verwenden, wenn Sie nur etwas auf der negativen Seite tun möchten. Beispielsweise:

if [[ True == False ]]; then
    :
else
    echo "true <> flase"
fi

Ohne die :Bash würde ein Syntaxfehler generiert.

Dies ist ein stark vereinfachtes Beispiel. Im Allgemeinen würden Sie eine solche Technik beim vorläufigen Codieren verwenden, wenn Sie dieses Codesegment noch nicht geschrieben haben und nur etwas benötigen, das keinen Fehler erzeugt.

WinEunuuchs2Unix
quelle
Gute Antwort, auch wenn es auf den ersten Blick nicht offensichtlich sein mag, dass dies am nützlichsten ist, wenn ein tatsächlicher Befehl innerhalb der Testbedingung ausgeführt wird. Beispielsweise if pgrep firefox >/dev/null ; then : ; else echo "Firefox not running"; fiwürde dies nur dann einen Fehler anzeigen, wenn Firefox nicht ausgeführt wird. Mit anderen Worten, wenn Sie etwas nur dann tun müssen, wenn der Befehl einen Fehler aufweist. In pgrep firefox || echo "Firefox not running"
gewisser
0

Ich habe es nur in einem Skript mit SSH-Befehlen verwendet, um Fehler im Skript zu vermeiden.

In diesem Fall möchte ich sehen, ob ein Benutzer eine Verbindung zu einer Reihe von Servern herstellen kann. Wenn die Verbindung in Ordnung ist, gibt der Remote-Host das Echo OK aus. Wenn die Verbindung fehlschlägt, antwortet SSH mit dem Fehler. Ich möchte jedoch, dass mein Skript mit 0 beendet wird und nicht mit dem Wert des SSH-Befehls, wenn dies fehlschlägt. Im Grunde genommen fange ich den SSH-Fehler ein, indem ich ihn ||mit dem Null-Befehl ODER-verknüpft :. Sieht aus wie das:

#!/bin/bash
for i in $(cat servers.txt); do
    echo -n "$i "; 
    ssh user@${i} 'echo OK' || :; 
done

Auf diese Weise erhalte ich die Ausgabe von SSH, aber nicht den Fehlercode:

....
swl06 ok
swl07 ok
swl08 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
swl09 ok
swl10 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
....
Michael J
quelle