GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Zirkuläre Namensreferenzen in der Bash-Shell-Funktion, aber nicht in Ksh?

Ich schreibe eine Reihe von Shell-Funktionen, die sowohl in Bash als auch in KornShell93 funktionieren sollen, aber bei Bash stoße ich auf eine „Circular Name Reference“-Warnung.

Das ist der Kern des Problems:

function set_it {
    typeset -n var="$1"

    var="hello:$var"
}

function call_it {
    typeset -n var="$1"

    set_it var
}

something="boff"
call_it something
echo "$something"

Ausführen:

$ ksh script.sh
hello:boff

$ bash script.sh
script.sh: line 4: warning: var: circular name reference
hello:

KornShell93 macht genau das, was ich will, aber Bash schlägt fehl und warnt auch vor der gleichen Sache in Zeile 2, wenn something Variable im Skript heißt var stattdessen.

Ich hätte gerne die var Variable lokal für jede Funktion sein, weshalb ich typeset verwende , aber Bash scheint es nicht zu mögen, eine Nameref auf eine Variable mit demselben Namen wie die Nameref selbst zu „dereferenzieren“. Ich kann local -n nicht verwenden oder declare -n da es in ksh einbrechen würde dem diese fehlen, und selbst wenn ich es getan hätte, löst es das Problem nicht.

Die einzige Lösung, die ich gefunden habe, besteht darin, in jeder Funktion eindeutige Variablennamen zu verwenden , was ziemlich albern erscheint, da sie lokal sind.

Das Bash-Handbuch sagt Folgendes über typeset :

typeset […]

-n Geben Sie jedem Namen den nameref -Attribut, wodurch es zu einem Namensverweis
auf eine andere Variable wird. Diese andere Variable
wird durch den Wert von name definiert . Alle Verweise und
Zuordnungen zu name , mit Ausnahme der Änderung von -n
-Attribut selbst, werden an der Variablen ausgeführt, auf die durch den Wert des Namens verwiesen wird.

[…]

Bei Verwendung in einer Funktion declare und typeset machen Sie jeden Namen
lokal, wie bei local Befehl, es sei denn, der -g Option
geliefert. Wenn auf einen Variablennamen =value folgt , wird der
Wert der Variable auf value gesetzt .

Es ist offensichtlich, dass ich etwas an Bashs Namensreferenzen und funktionslokalen Variablen nicht verstehe.

Die Frage ist also:Übersehe ich in diesem Fall etwas über Bashs Umgang mit Namensreferenzvariablen, oder ist dies ein Fehler/Fehlfunktion in Bash?

Aktualisieren :Ich arbeite derzeit mit GNU bash, version 4.3.39(1)-release (x86_64-apple-darwin15) sowie mit GNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0) . Die mit macOS gelieferte Bash ist zu alt, um überhaupt Namensreferenzen zu kennen.

Aktualisieren :Noch kürzer:

function bug {
    typeset -n var="$1"
    printf "%sn" "$var"
}

var="hello"
bug var

Ergibt bash: warning: var: circular name reference . Die var in der Funktion sollte einen anderen Geltungsbereich haben aus der var im globalen Rahmen. Dies erlegt dem Anrufer eine unnötige Beschränkung auf. Die Einschränkung lautet:„Sie dürfen Ihre Variablen nicht beliebig benennen, da es in dieser Funktion zu einem Namenskonflikt mit einem (lokalen) Nameref kommen kann.“

Verwandte:Wie wechselt man vom Root-Benutzer zu einem anderen Benutzer, der eine Nologin-Shell hat?

Akzeptierte Antwort:

Chet Ramey (Bash-Betreuer) sagt

Anfang des Jahres
gab es eine ausführliche Diskussion über Namerefs auf Bug-Bash. Ich habe einen vernünftigen Vorschlag, wie man dieses Verhalten ändern kann,
und ich werde ihn mir ansehen, nachdem bash-4.4 veröffentlicht wurde.

In der Zwischenzeit greife ich darauf zurück, die Namen meiner lokalen Nameref-Variablen leicht zu verschleiern, damit sie weder innerhalb der Bibliothek noch (hoffentlich) mit globalen Shell-Variablennamen kollidieren.

In bash 5.0 wurde dies geringfügig behoben (aber nicht wirklich behoben). Das folgende ist das beobachtete Verhalten:

$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello

Das zeigt, dass es funktioniert, aber es gibt auch ein paar Warnungen.

Der entsprechende NEWS-Eintrag lautet

i. A nameref name resolution loop in a function now resolves to a variable by
that name in the global scope.

Linux
  1. Anpassen der Bash-Shell

  2. Unterschied zwischen exportierten und nicht in Bash enthaltenen Shell-Variablen?

  3. Funktionen in Shell-Variablen?

  4. Python-Module wurden nicht über das Terminal gefunden, sondern auf der Python-Shell, Linux

  5. Zeigt nur den aktuellen Verzeichnisnamen (nicht den vollständigen Pfad) an der Bash-Eingabeaufforderung an

Bash-Funktionen

.bashrc vs. .bash_profile

Shell-Scripting Teil V:Funktionen in Bash

Nützliche Bash-Befehle, die Sie vielleicht nicht kennen

Tutorial zu Bash-Shell-Funktionen mit 6 praktischen Beispielen

`ssh <host>` ist eine Login-Shell, aber `ssh <host> <command>` nicht?