483 Stimmen

Was ist der Zweck des : (Doppelpunkt) GNU Bash builtin?

Was ist der Zweck eines Befehls, der nichts tut und kaum mehr als ein Vorspann für einen Kommentar ist, der aber selbst ein Shell-Builtin ist?

Es ist um etwa 40% pro Aufruf langsamer als das Einfügen eines Kommentars in Ihre Skripte, was wahrscheinlich stark von der Größe des Kommentars abhängt. Die einzigen möglichen Gründe, die ich dafür sehen kann, sind die folgenden:

# poor man's delay function
for ((x=0;x<100000;++x)) ; do : ; done

# inserting comments into string of commands
command ; command ; : we need a comment in here for some reason ; command

# an alias for `true'
while : ; do command ; done

Ich schätze, was ich wirklich suche, ist, welche historische Anwendung es gehabt haben könnte.

41voto

Dennis Williamson Punkte 322329

Es ist ähnlich wie pass in Python.

Eine Möglichkeit wäre, eine Funktion zu überbrücken, bis sie geschrieben wird:

future_function () { :; }

39voto

Ahi Tuna Punkte 1223

Wenn Sie eine Datei auf null Bytes kürzen möchten, was für das Löschen von Protokollen nützlich ist, versuchen Sie dies:

:> file.log

30voto

sepp2k Punkte 352762

Sie können es in Verbindung mit Backticks verwenden ( `` ), um einen Befehl auszuführen, ohne seine Ausgabe anzuzeigen, etwa so:

: `some_command`

Natürlich können Sie auch einfach some_command > /dev/null aber die : -Version ist etwas kürzer.

Trotzdem würde ich nicht empfehlen, das zu tun, da es die Leute nur verwirren würde. Es kam nur in den Sinn als eine mögliche Anwendung Fall.

27voto

ELLIOTTCABLE Punkte 15484

Es ist auch für polyglotte Programme nützlich:

#!/usr/bin/env sh
':' //; exec "$(command -v node)" "$0" "$@"
~function(){ ... }

Dies ist nun sowohl ein ausführbares Shell-Skript y ein JavaScript-Programm: Bedeutung ./filename.js , sh filename.js y node filename.js alle Arbeiten.

(Sicherlich eine etwas seltsame Verwendung, aber dennoch effektiv).


Einige Erklärungen, wie gewünscht:

  • Shell-Skripte werden Zeile für Zeile ausgewertet; und die exec beendet die Shell, wenn es ausgeführt wird, und Ersetzt seine Verarbeitung mit dem daraus resultierenden Befehl. Das bedeutet, dass das Programm für die Shell wie folgt aussieht:

    #!/usr/bin/env sh
    ':' //; exec "$(command -v node)" "$0" "$@"
  • Solange keine Parametererweiterung oder Aliasing im Wort vorkommt, jede Wort in einem Shell-Skript kann in Anführungszeichen gesetzt werden, ohne dass sich seine Bedeutung ändert; das bedeutet, dass ':' ist gleichbedeutend mit : (wir haben ihn hier nur in Anführungszeichen gesetzt, um die unten beschriebene JavaScript-Semantik zu erreichen)

  • ... und wie oben beschrieben, ist der erste Befehl in der ersten Zeile ein No-op (er wird übersetzt zu : // , oder wenn Sie es vorziehen, die Worte zu zitieren, ':' '//' . Beachten Sie, dass die // hat hier keine besondere Bedeutung, wie in JavaScript; es ist einfach ein bedeutungsloses Wort, das weggeworfen wird).

  • Der zweite Befehl in der ersten Zeile (nach dem Semikolon) schließlich ist das eigentliche Herzstück des Programms: Es ist der exec Aufruf, der die aufrufendes Shell-Skript mit einem Node.js-Prozess, der zur Auswertung aufgerufen wird der Rest des Drehbuchs.

  • In der Zwischenzeit wird die erste Zeile in JavaScript als String-Zeichenfolge ( ':' ), und dann ein Kommentar, der gelöscht wird; für JavaScript sieht das Programm also wie folgt aus:

    ':'
    ~function(){ ... }

    Da das String-Zeichen in einer eigenen Zeile steht, ist es eine No-op-Anweisung und wird daher aus dem Programm entfernt; das bedeutet, dass die gesamte Zeile entfernt wird und nur nur Ihren Programmcode (in diesem Beispiel die function(){ ... } Körper).

21voto

Sir Athos Punkte 8351

Selbstdokumentierende Funktionen

Sie können auch Folgendes verwenden : um die Dokumentation in eine Funktion einzubetten.

Angenommen, Sie haben ein Bibliotheksskript mylib.sh und bietet eine Vielzahl von Funktionen. Sie können entweder die Bibliothek ( . mylib.sh ) und rufen die Funktionen direkt danach auf ( lib_function1 arg1 arg2 ), oder vermeiden Sie es, Ihren Namespace zu überladen und rufen Sie die Bibliothek mit einem Funktionsargument auf ( mylib.sh lib_function1 arg1 arg2 ).

Wäre es nicht schön, wenn Sie auch Folgendes eingeben könnten mylib.sh --help und eine Liste der verfügbaren Funktionen und ihrer Verwendung erhalten, ohne die Funktionsliste im Hilfetext manuell pflegen zu müssen?

#!/bin/bash

# all "public" functions must start with this prefix
LIB\_PREFIX='lib\_'

# "public" library functions
lib\_function1() {
    : This function does something complicated with two arguments.
    :
    : Parameters:
    : '   arg1 - first argument ($1)'
    : '   arg2 - second argument'
    :
    : Result:
    : "   it's complicated"

    # actual function code starts here
}

lib\_function2() {
    : Function documentation

    # function code here
}

# help function
--help() {
    echo MyLib v0.0.1
    echo
    echo Usage: mylib.sh \[function\_name \[args\]\]
    echo
    echo Available functions:
    declare -f | sed -n -e '/^'$LIB\_PREFIX'/,/^}$/{/\\(^'$LIB\_PREFIX'\\)\\|\\(^\[ \\t\]\*:\\)/{
        s/^\\('$LIB\_PREFIX'.\*\\) ()/\\n=== \\1 ===/;s/^\[ \\t\]\*: \\?\['\\''"\]\\?/    /;s/\['\\''"\]\\?;\\?$//;p}}'
}

# main code
if \[ "${BASH\_SOURCE\[0\]}" = "${0}" \]; then
    # the script was executed instead of sourced
    # invoke requested function or display help
    if \[ "$(type -t - "$1" 2>/dev/null)" = function \]; then
        "$@"
    else
        --help
    fi
fi

Ein paar Anmerkungen zum Code:

  1. Alle "öffentlichen" Funktionen haben das gleiche Präfix. Nur diese sind dazu bestimmt, vom Benutzer aufgerufen und im Hilfetext aufgeführt zu werden.
  2. Die Selbstdokumentationsfunktion beruht auf dem vorherigen Punkt und verwendet declare -f um alle verfügbaren Funktionen aufzuzählen, und filtert sie dann durch sed, um nur Funktionen mit dem entsprechenden Präfix anzuzeigen.
  3. Es ist ratsam, die Dokumentation in einfache Anführungszeichen zu setzen, um unerwünschte Expansionen und das Entfernen von Leerzeichen zu verhindern. Auch bei der Verwendung von Apostrophen/Anführungszeichen im Text ist Vorsicht geboten.
  4. Sie könnten Code schreiben, um das Bibliothekspräfix zu internalisieren, d.h. der Benutzer muss nur eingeben mylib.sh function1 und es wird intern übersetzt in lib_function1 . Dies ist eine Übung, die dem Leser überlassen bleibt.
  5. Die Hilfefunktion heißt "--help". Dies ist ein bequemer (d.h. träger) Ansatz, der den Bibliotheksaufruf-Mechanismus nutzt, um die Hilfe selbst anzuzeigen, ohne eine zusätzliche Prüfung für $1 . Gleichzeitig wird Ihr Namespace unübersichtlich, wenn Sie die Bibliothek als Quelle angeben. Wenn Ihnen das nicht gefällt, können Sie entweder den Namen in etwas wie lib_help oder die Args tatsächlich auf --help im Hauptcode und rufen Sie die Hilfefunktion manuell auf.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X