Wann ist `_` eine Umgebungsvariable einer Bash-Shell?

10

Bash Manual sagt (Manpage, mein Schwerpunkt):

Wenn Bash einen externen Befehl aufruft, wird die Variable $_auf den vollständigen Pfadnamen des Befehls gesetzt und in seiner Umgebung an diesen Befehl übergeben.

Und ( spezielle Parameter ):

_

( $_, ein Unterstrich.) Legen Sie beim Start der Shell den absoluten Pfadnamen fest, der zum Aufrufen der Shell oder des Shell-Skripts verwendet wird, die bzw. das in der Umgebungs- oder Argumentliste übergeben wird. Erweitert anschließend nach der Erweiterung zum letzten Argument des vorherigen Befehls. Stellen Sie außerdem den vollständigen Pfadnamen ein, der zum Aufrufen jedes ausgeführten und in die in diesen Befehl exportierte Umgebung platzierten Befehls verwendet wird. Beim Überprüfen von E-Mails enthält dieser Parameter den Namen der E-Mail-Datei.

  1. In einer Bash-Shell laufe ich:

    $ bash
    $ export | grep '_=' 

    Laut Handbuch _sollte eine Umgebungsvariable der neuen Bash-Shell sein. exportsoll alle Umgebungsvariablen der neuen Bash-Shell ausgeben, gibt aber nicht aus _. Ich frage mich also, ob _es sich um eine Umgebungsvariable der neuen Bash-Shell handelt.

  2. Tatsächlich passiert in jeder Bash-Shell dasselbe

    $ export | grep '_='

    gibt nichts aus. Ich frage mich also, ob _es jemals eine Umgebungsvariable einer Bash-Shell gibt.

  3. Zum Vergleich:

    $ dash
    $ export  | grep '_='        
    export _='/bin/dash'

Mein Beitrag ist inspiriert von Mikes Kommentar und Stephanes Antwort .

Tim
quelle
1
Es ist eine Shell-Variable und wird an die Umgebung des Befehls übergeben . Es wird nicht unbedingt in die Umgebung der Shell exportiert . exportist ein eingebautes Gerät, aber wenn Sie es verwenden printenv _, zeigt es Ihnen, wie es aufgerufen wurde: /usr/bin/printenvauf diesem System.
Toby Speight
Beachten Sie, dass bash -c export | grep _=(von Bash), wird zeigen , wie die Eltern - Shell den aufgerufenen bashBefehl, obwohl $_ist ungesetzt in den Eltern.
Toby Speight

Antworten:

13

Ja, _ist eine Umgebungsvariable der neuen Bash-Shell. Sie können das sehen, indem Sie laufen

tr '\0' '\n' < /proc/$$/environ | grep _=

innerhalb der Shell: Zeigt den Inhalt der ursprünglichen Umgebung der Shell an. Sie werden es in der ersten Shell nicht sehen, da es vor dem Start keine vorherige Shell gab, um es festzulegen.

Das Erweitern $_in Bash bezieht sich auf den _speziellen Parameter, der bis zum letzten Argument des vorherigen Befehls erweitert wird. (Intern behandelt Bash dies mithilfe einer _Shell-Variablen, die jedes Mal aktualisiert wird, wenn ein Befehl analysiert wird. Dies ist jedoch wirklich ein Implementierungsdetail. Sie wird jedes Mal "nicht exportiert", wenn ein Befehl analysiert wird. ) Wird nicht angezeigtexport , _da dies nicht der Fall ist eine Variable, die als exportiert markiert ist; Sie können es jedoch in der Ausgabe von sehen set.

Im ersten Beispiel die neue Shell Parsen Bash und führt die Befehle in die Startdateien, so beim Laufen explore | grep '-=', _wurde bereits überschrieben und markiert als nicht exportiert.

In diesem dashBeispiel scheint keine Startdatei ausgeführt zu werden. Sie sehen die Variable also als Umgebungsvariable, die von Bash vor der Ausführung festgelegt wurde dash.

Stephen Kitt
quelle
Vielen Dank. Warum wird in der neuen Bash-Shell nichts export | grep '_='ausgegeben? Warum wird in der ursprünglichen Bash-Shell nichts tr '\0' '\n' < /proc/$$/environ | grep _=ausgegeben?
Tim
9

exportohne Argumente listet alle exportierten Variablen auf . _ist keine Variable, sondern wird als spezieller Parameter aufgeführt .

Etwas verwirrend _wäre auch ein gültiger Name für eine Variable , im Gegensatz zu den Namen der anderen speziellen Parameter. Zumindest Bash 4.4 erlaubt Zuweisungen ohne Beanstandungen. Es ist einfach nicht nützlich, weil der Spezialeffekt den Wert sofort überschreibt.

ilkkachu
quelle
2
Viel Spaß beim Versuch, _als Variable zu verwenden ;-). Es ist praktisch nur schreibgeschützt und der Wert geht sofort verloren.
Stephen Kitt
1
Intern wird Bash auch _als Variable behandelt, weshalb es in der Ausgabe von angezeigt wird set. Es kann jedoch nicht als exportiert markiert werden, soweit ich feststellen kann.
Stephen Kitt
2
@StephenKitt, aber Bash 4.4 erlaubt das Markieren als schreibgeschützt. Oder eine ganze Zahl. Mit etwas komischen Ergebnissen.
Ilkkachu
1
Ha, schöner Fund, das ist ziemlich amüsant!
Stephen Kitt
5

Nicht jede Shell-Variable wird als exportiert markiert, wie Sie in der Ausgabe von sehen können declare -p.

Es macht keinen Sinn bash, $_als exportiert zu markieren, da diese Variable automatisch zur Umgebung untergeordneter Prozesse hinzugefügt wird, jedoch mit einem anderen Wert als dem, den sie (zu diesem Zeitpunkt) in der Shell hat.

Das Anzeigen als exportiert würde den Benutzer nur verwirren, was mit der Umgebung externer Befehle passieren wird.

Alle "Laufzeitvariablen" BASH*werden nicht exportiert.

Hauke ​​Laging
quelle