Wurden Backticks (zB `cmd`) in * sh-Shells verworfen?

118

Ich habe diesen Kommentar unter Unix und Linux sowie auf anderen Websites, die die Formulierung "Backticks sind veraltet" verwenden, in Bezug auf Shells wie Bash und Zsh oft gesehen.

Ist diese Aussage richtig oder falsch?

slm
quelle
Siehe Warum nicht Anführungszeichen in einem Shell - Skript zurück , um mir helfen , cdin ein Verzeichnis für ein Beispiel , warum $(...)Schreibweise ist einfacher zu benutzen als verschachtelte Rück Anführungszeichen.
Jonathan Leffler
2
Pointe hier
Trevor Boyd Smith
1
Mindestens ein Unix, AIX, hat dokumentiert, dass Backticks veraltet sind . "Obwohl die Backquote-Syntax von ksh akzeptiert wird, wird sie von den X / Open Portability Guide Issue 4- und POSIX-Standards als veraltet angesehen. Diese Standards empfehlen, dass tragbare Anwendungen die Syntax $ (Befehl) verwenden." ibm.com/support/knowledgecenter/ssw_aix_71/com.ibm.aix.osdevice/…
Christopher
Ich habe einen deutlichen Unterschied in "GNU bash, version 3.2.57 (1) -release (x86_64-apple-darwin14)" auf Mac 10.10: matchingLines=$( grep -n '\$-PARAMETER' ... | ... )funktioniert, matchingLines= backtick the same stuff backtickfunktioniert nicht - scheint den Backslash in Backslash-Dollar zu verlieren. (Es ist nicht mein Drehbuch ...)
Denis

Antworten:

126

Es gibt zwei verschiedene Bedeutungen von "veraltet".

veraltet sein: (hauptsächlich von einer Software-Funktion) verwendbar sein, aber als veraltet angesehen und am besten vermieden werden, typischerweise weil es abgelöst wurde.

- New Oxford American Dictionary

Durch diese Definition Backticks sind veraltet.

Veralteter Status kann auch darauf hinweisen, dass das Feature in Zukunft entfernt wird.

- Wikipedia

Nach dieser Definition werden Backticks nicht veraltet.

Wird weiterhin unterstützt:

Unter Bezugnahme auf die Open Group-Spezifikation für Shell-Befehlssprachen , insbesondere Abschnitt "2.6.3 Befehlssubstitution", ist ersichtlich, dass beide Formen der Befehlssubstitution, Backticks ( `..cmd..`) oder Dollar Parens ( $(..cmd..)), weiterhin unterstützt werden, soweit die Spezifikation dies zulässt .

Auszug

Durch die Befehlsersetzung kann die Ausgabe eines Befehls anstelle des Befehlsnamens selbst ersetzt werden. Die Befehlsersetzung erfolgt, wenn der Befehl wie folgt beigefügt ist:

          $(command)

          or (backquoted version):

          `command`

Die Shell erweitert die Befehlsersetzung, indem sie den Befehl in einer Subshell-Umgebung ausführt (siehe Shell-Ausführungsumgebung) und die Befehlsersetzung (Befehlstext plus $()Anführungszeichen oder Anführungszeichen) durch die Standardausgabe des Befehls ersetzt und Sequenzen von einem oder mehreren entfernt <newline> Zeichen am Ende der Ersetzung. Eingebettete <newline> -Zeichen vor dem Ende der Ausgabe werden nicht entfernt. Sie können jedoch als Feldbegrenzer behandelt und während der Feldaufteilung entfernt werden, je nach dem Wert von IFS und der gültigen Anführungszeichen. Wenn die Ausgabe null Bytes enthält, ist das Verhalten nicht angegeben.

Innerhalb des Befehlsersetzungsstils mit Anführungszeichen behält <Backslash> seine wörtliche Bedeutung bei, es sei denn, es folgt: '$', ' \`' oder <Backslash> . Die Suche nach dem passenden Backquote wird durch das erste nicht zitierte Backquote ohne Escapezeichen erfüllt. Wenn bei dieser Suche ein nicht maskiertes Backquote in einem Shell-Kommentar, einem Here-Document, einer eingebetteten Befehlsersetzung des $(command)Formulars oder einer Zeichenfolge in Anführungszeichen gefunden wird, treten undefinierte Ergebnisse auf. Eine Zeichenfolge in einfachen oder doppelten Anführungszeichen, die in der `...`Sequenz beginnt, aber nicht endet, " " führt zu undefinierten Ergebnissen.

Mit dem $(command)Formular bilden alle Zeichen, die auf die offene Klammer bis zur passenden schließenden Klammer folgen, den Befehl. Für den Befehl kann ein beliebiges gültiges Shell-Skript verwendet werden, mit Ausnahme eines Skripts, das ausschließlich aus Umleitungen besteht und nicht angegebene Ergebnisse liefert.

Warum sagen dann alle, dass Backticks veraltet sind?

Da die meisten der Anwendungsfälle sollte die Verwendung des Dollars werden machen parens statt Backticks bilden. (Im obigen ersten Sinne veraltet.) Viele der seriösesten Websites (einschließlich U & L) geben dies ebenfalls an, so dass es sich um fundierte Ratschläge handelt. Dieser Rat sollte nicht mit einem nicht existierenden Plan verwechselt werden, die Unterstützung für Backticks von Muscheln zu entfernen.

  • BashFAQ # 082 - Warum wird $ (...) gegenüber `...` (Backticks) bevorzugt?

    Auszug

    `...`ist die Legacy-Syntax, die nur von den ältesten nicht POSIX-kompatiblen Bourne-Shells benötigt wird. Es gibt mehrere Gründe, die $(...)Syntax immer zu bevorzugen :

    ...

  • Bash Hackers Wiki - Veraltete und veraltete Syntax

    Auszug

    Dies ist die ältere Bourne-kompatible Form der Befehlsersetzung . Sowohl die `COMMANDS`und $(COMMANDS)Syntaxen werden durch POSIX spezifiziert, aber diese ist stark bevorzugt, obwohl der ehemalige leider immer noch sehr weit verbreitet in Skripten ist. Kommandosubstitutionen neuen Stils werden von jeder modernen Shell (und einigen) weitgehend implementiert. Der einzige Grund für die Verwendung von Backticks ist die Kompatibilität mit einer echten Bourne-Shell (wie Heirloom). Ersetzungen von Backtick-Befehlen erfordern ein spezielles Escape-Zeichen, wenn sie verschachtelt sind, und Beispiele, die in freier Wildbahn gefunden werden, werden häufig falsch zitiert. Siehe: Warum wird $ (...) gegenüber `...` (Backticks) bevorzugt? .

  • POSIX-Standardbegründung

    Auszug

    Aufgrund dieser inkonsistenten Verhaltensweisen wird die von hinten angegebene Variante der Befehlsersetzung nicht für neue Anwendungen empfohlen, die Befehlsersetzungen verschachteln oder versuchen, komplexe Skripts einzubetten.

HINWEIS: Diese dritte Auszug (oben) geht auf mehrere Situationen zu zeigen , wo Backticks wird einfach nicht funktionieren, aber die neuere Dollar Pars Verfahren der Fall ist, mit dem folgenden Absatz beginnen:

Darüber hinaus unterliegt die Syntax in Anführungszeichen historischen Einschränkungen für den Inhalt des eingebetteten Befehls. Während das neuere "$ ()" - Formular alle gültigen eingebetteten Skripte verarbeiten kann, kann das Formular mit Anführungszeichen einige gültige Skripte, die Anführungszeichen enthalten, nicht verarbeiten.

Wenn Sie diesen Abschnitt weiterlesen, werden die Fehler hervorgehoben, um zu zeigen, wie sie bei Verwendung von Backticks fehlschlagen würden, arbeiten Sie jedoch mit der neueren Dollar-Parens-Notation.

Schlussfolgerungen

Es ist also vorzuziehen, dass Sie Dollar-Parens anstelle von Backticks verwenden, aber Sie verwenden nicht wirklich etwas, das technisch "veraltet" ist, wie in "Das wird irgendwann nicht mehr funktionieren".

Nachdem Sie dies alles gelesen haben, sollten Sie die Möglichkeit haben, Dollar-Parens zu verwenden, es sei denn, Sie benötigen ausdrücklich die Kompatibilität mit einer echten Original-Bourne-Shell, die nicht von POSIX stammt.

slm
quelle
26
Durch die meisten der Bedeutungen von veraltet , ich (und Sie) würde sagen , dass Backticks sind veraltet. Es ist meistens eine Terminologiefrage.
Stéphane Chazelas
4
@StephaneChazelas - Einverstanden! Ich werde ppl weiterhin mitteilen, dass sie veraltet sind, Backticks jedoch nicht in dem Sinne offiziell "veraltet" sind, dass sie in naher Zukunft aktiv aus der Codebasis einer Shell entfernt werden. Zumindest keine, die mir bekannt sind.
slm
3
Meine Interpretation ist, dass Backquotes nur deshalb unterstützt werden, weil sie zu tief im vorhandenen Code verankert sind, um formal abgelehnt zu werden. Ich habe noch nie ein Argument für die weitere Verwendung in neuem Code gehört.
Chepner
3
@slm Ja, ich denke du hast es verstanden - ich wurde weggezogen und habe es nicht bemerkt. Es gibt fast keinen Grund, diese Dinge zu verwenden, außer dass es beim Schichten von Unterschalen ein bisschen sauberer sein kann, also $( cmd `cmd`)ein bisschen weniger chaotisch als $( cmd $(cmd))- es ist einfacher zu lesen. Ich habe ein veraltetes Feature in Software immer als ein offiziell für das Entfernen durch den Upstream gekennzeichnetes Feature angesehen - und ich habe noch nie davon gehört. Es ist mir egal - ich habe keine Liebe zum Grab.
mikeserv
3
Möglicherweise möchten Sie das folgende Zitat aus der POSIX-Standardbegründung hinzufügen : Aufgrund dieses inkonsistenten Verhaltens wird die von hinten angegebene Variante der Befehlssubstitution nicht für neue Anwendungen empfohlen, die Befehlssubstitutionen verschachteln oder versuchen, komplexe Skripts einzubetten. Dies ist zwar keine formale Ablehnung, da der Abschnitt mit den Begründungen informativ und nicht normativ ist, es wird jedoch empfohlen, die weitere Verwendung von Backticks zu vermeiden.
JW013
15

Es ist nicht veraltet, aber backticks ( `...`) ist die Legacy-Syntax, die nur von den ältesten nicht POSIX-kompatiblen Borowski-Shells benötigt wird. Es $(...)ist POSIX und wird aus mehreren Gründen bevorzugt:

  • Backslashes ( \) in Backticks werden auf nicht offensichtliche Weise behandelt:

    $ echo "`echo \\a`" "$(echo \\a)"
    a \a
    $ echo "`echo \\\\a`" "$(echo \\\\a)"
    \a \\a
    # Note that this is true for *single quotes* too!
    $ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar" 
    foo is \, bar is \\
    
  • Verschachtelte Anführungszeichen $()sind viel praktischer:

    echo "x is $(sed ... <<<"$y")"

    Anstatt von:

    echo "x is `sed ... <<<\"$y\"`"

    oder etwas schreiben wie:

    IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`

    weil $()verwendet einen völlig neuen Kontext für das Zitieren

    Dies ist nicht portabel, da Bourne- und Korn-Shells diese Backslashes benötigen, Bash und Dash dagegen nicht.

  • Die Syntax für die Verschachtelung von Befehlsersetzungen ist einfacher:

    x=$(grep "$(dirname "$path")" file)

    als:

    x=`grep "\`dirname \"$path\"\`" file`

    Da $()ein völlig neuer Kontext für das Zitieren erzwungen wird, ist jede Befehlsersetzung geschützt und kann für sich allein behandelt werden, ohne besondere Bedenken hinsichtlich des Zitierens und des Ausweichens. Mit Backticks wird es ab zwei Levels immer hässlicher.

    Einige weitere Beispiele:

    echo `echo `ls``      # INCORRECT
    echo `echo \`ls\``    # CORRECT
    echo $(echo $(ls))    # CORRECT
    
  • Es behebt das Problem eines inkonsistenten Verhaltens bei der Verwendung von Anführungszeichen:

    • echo '\$x' Ausgänge \$x
    • echo `echo '\$x'` Ausgänge $x
    • echo $(echo '\$x') Ausgänge \$x
  • Die Backticks-Syntax unterliegt historischen Einschränkungen für den Inhalt des eingebetteten Befehls und kann einige gültige Skripts mit Anführungszeichen nicht verarbeiten, während das neuere $()Formular alle gültigen eingebetteten Skripts verarbeiten kann.

    Diese ansonsten gültigen eingebetteten Skripte funktionieren beispielsweise nicht in der linken Spalte, sondern in der rechten IEEE :

    echo `                         echo $(
    cat <<\eof                     cat <<\eof
    a here-doc with `              a here-doc with )
    eof                            eof
    `                              )
    
    
    echo `                         echo $(
    echo abc # a comment with `    echo abc # a comment with )
    `                              )
    
    
    echo `                         echo $(
    echo '`'                       echo ')'
    `                              )
    

Daher sollte die Syntax für die $vorab festgelegte Befehlssubstitution die bevorzugte Methode sein, da sie mit sauberer Syntax visuell klar ist (die Lesbarkeit von Mensch und Maschine verbessert), schachtelbar und intuitiv ist, die innere Analyse getrennt ist und auch konsistenter ist (mit Alle anderen Erweiterungen, die in doppelten Anführungszeichen angegeben werden, bei denen Backticks die einzige Ausnahme darstellen und `Zeichen leicht getarnt werden können, wenn "sie noch schwieriger lesbar sind, insbesondere bei kleinen oder ungewöhnlichen Schriftarten.

Quelle: Warum wird Backticks $(...)vorgezogen `...`? bei BashFAQ

Siehe auch:

Kenorb
quelle