Nachdem ich die Antwort von ilkkachu auf diese Frage gelesen hatte , erfuhr ich von der Existenz der declare
(mit Argument -n
) integrierte Shell.
help declare
bringt:
Festlegen von Variablenwerten und Attributen.
Deklarieren Sie Variablen und geben Sie ihnen Attribute. Wenn keine NAMEs angegeben sind, zeigen Sie die an Attribute und Werte aller Variablen.
-n … macht NAME zu einem Verweis auf die Variable, die durch ihren Wert benannt wird.
I. Fragen Sie nach einer allgemeinen Erklärung mit einem Beispiel zu declare
, da ich die man
nicht verstehe. Ich weiß, was eine Variable ist und erweitere sie, aber ich vermisse immer noch die man
auf declare
(Variablenattribut?).
Vielleicht möchten Sie dies anhand des Codes von ilkkachu in der Antwort erklären:
#!/bin/bash function read_and_verify { read -p "Please enter value for "$1": " tmp1 read -p "Please repeat the value to verify: " tmp2 if [ "$tmp1" != "$tmp2" ]; then echo "Values unmatched. Please try again."; return 2 else declare -n ref="$1" ref=$tmp1 fi }
Kommentare
- Verwandte Themen: unix.stackexchange.com/questions/522366/…
Antwort
In den meisten Fällen reicht eine implizite Deklaration in bash
asdf="some text"
Manchmal möchten Sie jedoch, dass der Wert einer Variablen nur eine Ganzzahl ist (falls er sich später ändern sollte, auch automatisch, kann er nur in geändert werden eine Ganzzahl (in einigen Fällen standardmäßig Null) und kann Folgendes verwenden:
declare -i num
oder
declare -i num=15
Manchmal möchten Sie Arrays, und dann benötigen Sie declare
declare -a asdf # indexed type
oder
Gute Tutorials zu Arrays finden Sie in bash
, wenn Sie mit der Suchzeichenfolge“ bash array tutorial „(ohne Anführungszeichen) im Internet surfen, z Beispiel
linuxconfig.org/how-to-use-arrays-in-bash-script
Ich denke, dies sind die häufigsten Fälle, wenn Sie Variablen deklarieren.
Bitte beachten Sie auch, dass
- in einer Funktion
declare
macht die Variable lokal (in der Funktion) -
ohne Namen, listet alle Variablen (in der aktiven Shell) auf
declare
Schließlich erhalten Sie eine kurze Zusammenfassung der Funktionen des in die Shell integrierten Befehls declare
in mit dem Befehl
help declare
Kommentare
- Hallo vom OP! Ich finde Ihre Antwort großartig und habe sie positiv bewertet und danke Ihnen für diese meiner Meinung nach sehr didaktische Antwort. Ich habe gerade eine kleinere Änderung vorgeschlagen, die meiner bescheidenen Meinung nach das Lesen für Neulinge noch einfacher und zugänglicher macht. Bitte gehen Sie diesen Vorschlag durch.
- Ich habe gerade gesehen, dass
user:muru
dafür gestimmt hat, die Bearbeitung abzulehnen. Bitte wissen Sie, dass ich und muru “ “ mehrmals in den verschiedenen Abschnitten dieser Website zusammengestoßen sind und ich davon ausgehe, dass seine Ablehnung nicht ‚ ist nicht objektiv und tatsächlich schädlich im Gegensatz zu den direkten Änderungen, die auf der Seite mit den Bearbeitungsvorschlägen hier dargestellt sind: unix.stackexchange.com/review/suggested -edits / 325749 - @JohnDoea, ich habe gesehen, dass auch ein anderer Benutzer Ihre Änderungen abgelehnt hat. Ich denke, einige Ihrer Änderungen sind gut, aber einige von ihnen ändern die Nachricht von dem, was ich beabsichtigt habe, sodass ich sie nicht mag. Ich kann die Antwort so bearbeiten, dass sie meiner Meinung nach gute Änderungen enthält.
- Danke; Wie Sie wahrscheinlich wissen, ist das Ablehnen von Änderungen in SE weitaus häufiger als das Akzeptieren von Änderungen (auch nur teilweise). Vielen Dank, dass Sie mich wissen lassen, dass ein anderer Benutzer die Bearbeitung abgelehnt hat (ich habe ‚ vorher nicht ehrlich gesehen) und dass Sie erwogen haben, zumindest einige meiner Änderungen in Ihre Antwort einzufügen. Ich respektiere so viel,
Antwort
Die Ausgabe von help declare
ist ziemlich knapp. Eine klarere Erklärung finden Sie in man bash
oder info bash
– letzteres ist die Quelle für das Folgende.
Zunächst einige Definitionen. Informationen zu Variablen und Attributen :
Ein Parameter ist eine Entität, die Werte speichert. … Eine Variable ist ein Parameter, der mit
name
gekennzeichnet ist. Eine Variable hat einen Wert und null oder mehr Attribute . Attribute werden mit dem integrierten Befehldeclare
zugewiesen …
Und über die declare
eingebaute :
declare
declare [-aAfFgilnrtux] [-p] [name[=value] …]
Deklarieren Sie Variablen und geben Sie ihnen Attribute. Wenn keine Namen angegeben sind, zeigen Sie stattdessen die Werte der Variablen an.
…
-n
Geben Sie jeweils name das Attribut nameref , wodurch es zu einem Namensverweis auf eine andere Variable wird. Diese andere Variable wird durch den Wert von name definiert. Alle Verweise, Zuweisungen und Attributänderungen an name , mit Ausnahme derjenigen, die das Attribut-n
selbst verwenden oder ändern, werden für die Variable ausgeführt, auf die verweist Wert von name . …
Beachten Sie, dass Namensreferenzvariablen nur in Bash 4.3 oder höher 1 verfügbar sind
Für eine nützliche Einführung in declare
und Variablenattribute in Bash verweise ich Sie auf Antwort auf “ Was tun declare name
und declare -g
? “ (der sich jedoch hauptsächlich auf den Bereich „Variablen“ konzentriert).
Grundsätzlich 2 , declare name=[value]
entspricht der Zuweisung name=[value]
, mit der Sie wahrscheinlich vertraut sind. In beiden Fällen wird name
die Null zugewiesen Wert, wenn value
fehlt.
Beachten Sie, dass die geringfügig andere declare name
stattdessen nicht festgelegt wird die Variable name
3 :
$ declare name ## With the -p option, declare is used to display ## attributes and values of variables $ declare -p name declare -- name ## "name" exists ## Parameter expansion can be used to reveal if a variable is set: ## "isunset" is substituted to "name" only if unset $ echo "${name-isunset}" isunset
Somit kann die Variable name
:
- deklariert sein und nicht gesetzt nach
declare name
; - deklariert und set mit null als Wert nach
name=
oderdeclare name=
; - deklariert , set und mit einem nicht null -Wert nach
name=value
oder .
Im Allgemeinen erstellt declare [options] name=value
- die Variable
name
– Dies ist ein Parameter mit einem Namen, der wiederum nur einen Teil des Speichers darstellt, den Sie zum Speichern von Informationen verwenden können. 4 ; - weist zu der Wert
value
darauf; - setzt optional die Attribute von
name
, die beide Arten von Werten definieren kann speichern (streng genommen nicht in Form eines Typs , da die Sprache von Bash nicht typisiert ist) und die Art und Weise, wie sie manipuliert werden kann.
Attribute sind wahrscheinlich einfacher mit einem Beispiel zu erklären: Wenn Sie declare -i name
verwenden, wird das Attribut “ Ganzzahl “ festgelegt von name
, so dass es als Ganzzahl behandelt wird; Unter Angabe des Handbuchs wird die arithmetische Auswertung “ durchgeführt, wenn der Variablen ein Wert :
## Let"s compare an ordinary variable with an integer $ declare var $ declare -i int $ var="1+1" $ int="1+1" $ echo "$var" 1+1 ## The literal "1+1" $ echo "$int" 2 ## The result of the evaluation of 1+1
In Anbetracht von Im obigen Code von ilkkachu geschieht Folgendes:
-
Eine Variable mit dem Namen
ref
wird mit der “ nameref “ Attributsatz, und der Inhalt von$1
(das erste Positionsargument) wird zugewiesen it:declare -n ref="$1"
Das Ziel einer Namensreferenzvariablen wie
ref
soll den Namen einer anderen Variablen enthalten, die im Allgemeinen nicht im Voraus bekannt ist, möglicherweise weil wir möchten, dass sie dynamisch definiert wird (z. B. weil wir einen Code wiederverwenden und haben möchten angewendet auf mehrere Variablen) und auf bieten eine bequeme Möglichkeit, darauf zu verweisen (und es zu manipulieren). (Nicht die einzige: Indirektion ist eine Alternative; siehe Shell-Parametererweiterung ). -
Wann Der Wert der Variablen
tmp1
wirdref
zugewiesen:ref=$tmp1
Eine zusätzliche Variable, deren Name der Wert von
ref
ist, wird implizit deklariert. Der Wert vontmp1
wird der implizit deklarierten Variablen auch indirekt durch diese explizite Zuordnung zuref
zugewiesen .
Im Kontext von Ihrer verknüpften Frage rufen Sie read_and_verify
as
read_and_verify domain "Prompt text here..."
deklariert die Variable domain
und weisen Sie ihm den Wert tmp1
(dh die Benutzereingabe) zu. Es ist genau darauf ausgelegt, den mit dem Benutzer interagierenden Code wiederzuverwenden und eine nameref-Variable zu nutzen domain
und einige andere Variablen deklarieren.
Um den impliziten Teil genauer zu betrachten, können wir den Prozess Schritt für Schritt reproduzieren:
## Assign a value to the first positional argument $ set -- "domain" ## Declare the same "tmp1" variable as in your code $ tmp1="value for domain" ## Declare a "ref" variable with the nameref attribute set and ## assign the value "domain" to it $ declare -n ref="$1" ## Note that there is no "domain" variable yet $ declare -p domain bash: declare: domain: not found ## Assign a value to "ref" and, indirectly, to the "domain" variable ## that is implicitly declared $ ref=$tmp1 ## Verify that a variable named "domain" now exists, and that ## its value is that of "tmp1" $ declare -p domain declare -- domain="value for domain" ## Verify that "ref" is actually a reference to "domain" $ domain="new value" $ echo "$domain" new value $ declare -p ref declare -n ref="domain" $ echo "$ref" new value
1 Referenz: CHANGES -Datei, Abschnitt “ 3. Neue Funktionen in Bash „, Punkt “ w „.
Dies kann relevant sein: zum Beispiel CentOS Linux 7.6 (derzeit das neueste Version) wird mit Bash 4.2 ausgeliefert.
2 Wie üblich mit Shell Builtins, eine erschöpfende und kurze Erklärung ist schwer zu finden, da sie verschiedene, möglicherweise heterogene Aktionen ausführen. Ich werde mich darauf konzentrieren, nur Attribute zu deklarieren, zuzuweisen und festzulegen, und ich werde in Betracht ziehen, Attribute außerhalb des Geltungsbereichs dieser Antwort aufzulisten, zu erfassen und zu entfernen.
3 Dieses Verhalten von declare -p
wurde in Bash 4.4 eingeführt. Referenz: CHANGES -Datei, Abschnitt “ 3. Neue Funktionen in Bash „, Punkt “ f „.
As G-Man , auf den in Kommentaren hingewiesen wurde, in Bash 4.3 declare name; declare -p name
gibt einen Fehler aus. Sie können jedoch weiterhin überprüfen, ob name
mit declare -p | grep "declare -- name"
vorhanden ist.
4 FullBashGuide, Parameter auf mywiki.wooledge.org
Kommentare
- (1) Ich kann die Ergebnisse, die Sie in Ihrem ersten Codeblock anzeigen, nicht reproduzieren:
declare name
gefolgt vondeclare -p name
ergibt „bash: declare: name: not found“. (Obwohldeclare -p | grep na
declare -- name
ergibt.) (2) Ich glaube, dass es etwas irreführend ist,echo "${name-isunset}"
im Kontext vondeclare name
, da eine nicht deklarierte (dh undefinierte) Variable genauso behandelt wird wie eine deklarierte aber unset Variable. (3) Vielleicht möchten Sie erwähnen, dass namerefs nur in Bash-Version 4.3 und höher verfügbar sind. - @ G-Man Vielen Dank für Ihre Anmerkungen! Ich ‚ werde sie so schnell wie möglich ansprechen und ‚ werde meine Antwort gegebenenfalls aktualisieren. Was (1) betrifft, liefert meine
GNU bash, version 5.0.7(1)-release (x86_64-pc-linux-gnu)
unter Arch Linux immer noch die Ergebnisse, die ich gezeigt habe. Vielleicht wurde dieses Verhalten erst kürzlich eingeführt. Ich werde das ‚ untersuchen. - Ja; Ich ‚ verwende nur Version 4.3.
- @ G-Man Antwort aktualisiert mit Anmerkungen zu (1) und (3). Über (2): Ich wollte veranschaulichen, dass
declare x
‚x
nicht setzt. währenddeclare x=
dies tut. Ich konnte ‚ keinen Verweis finden, um die Behauptung zu stützen, dassdeclare -- x
(als Ausgabe vondeclare -p x
) bedeutet “ nicht gesetzt „, währenddeclare -- x=""
set „; Daher habe ich die Erweiterung${parameter-word}
eingeführt, auch wenn sie nicht zwischen “ nicht gesetztem “ unterscheiden kann und “ existiert nicht ‚ „, wie Sie hervorheben. Ich ‚ bin mir jedoch nicht sicher, wie ich dies in meiner Antwort klarstellen kann (ohne den Leser vom Punkt abzulenken).
Antwort
Ich werde versuchen, dies zu erklären, aber verzeihen Sie mir, wenn ich dem von Ihnen angegebenen Beispiel nicht folge. Ich werde lieber versuchen, Sie auf meinem eigenen, anderen Ansatz zu führen.
Sie sagen, Sie verstehen bereits Konzepte wie „Variablen“ und „Erweitern“ usw., also werde ich nur einige überfliegen Hintergrundwissen, das sonst einen tieferen Fokus erfordern würde.
Zunächst möchte ich sagen, dass grundlegend können Sie mit dem Befehl declare
Bash lediglich mitteilen, dass Sie einen variablen Wert benötigen (dh einen Wert, der sich während der Skriptausführung möglicherweise ändert) Verweisen Sie auf diesen Wert mit einem bestimmten Namen, genau dem Namen, den Sie neben dem Befehl declare
selbst angeben.
Das heißt:
declare foo="bar"
teilt Bash mit, dass Sie Ich möchte, dass die Variable mit dem Namen foo
den Wert bar
hat.
Aber … Moment mal … wir können Tun Sie das, ohne declare
zu verwenden. Wie in:
foo="bar"
Sehr wahr.
Nun Es kommt also vor, dass die obige einfache Zuweisung tatsächlich eine implizite Methode ist, um tatsächlich eine Variable zu deklarieren.
( Es kommt auch vor, dass eine einiger Möglichkeiten zu ändere den Wert der Variablen mit dem Namen foo
; tatsächlich ist es genau der direkteste, prägnanter, offensichtlicher, direkter Weg … aber es ist nicht der einzige … Ich werde später darauf zurückkommen … ).
Aber dann, wenn es so ist Es ist durchaus möglich, einen „Namen zu deklarieren, der der Kürze halber Variablenwerte markiert“ (im Folgenden nur „Variable“), ohne declare
zu verwenden. Warum sollten Sie das jemals wollen? Verwenden Sie diesen pompösen Befehl „deklarieren“?
Die Antwort liegt in der Tatsache, dass die obigen Implikationen Um eine Variable zu deklarieren (foo="bar"
), wird Bash implizit dazu veranlasst, diese Variable als den Typ zu betrachten, der im typischen Verwendungsszenario für eine Shell am häufigsten verwendet wird
Ein solcher Typ ist der Zeichenfolgentyp, dh eine Folge von Zeichen ohne besondere Bedeutung. Daher erhalten Sie eine Zeichenfolge, wenn Sie die implizite Deklaration verwenden.
Als Programmierer müssen Sie jedoch manchmal eine Variable eher als z. B. eine Zahl betrachten, für die Sie arithmetisch arbeiten müssen Operationen .. und die Verwendung einer impliziten Deklaration wie foo=5+6
bewirkt nicht, dass Bash foo
as den Wert 11 zuweist Sie könnten erwarten. Vielmehr wird foo
die Reihenfolge der drei Zeichen zugewiesen 5
+
6
.
Also … Sie müssen Bash mitteilen, dass foo
als Zahl und nicht als Zahl betrachtet werden soll Zeichenfolge .. und dafür ist eine explizite declare
nützlich.
Sagen Sie einfach:
declare -i foo=5+6 # <<- note the "-i" option: it means "integer"
und Bash rechnen gerne für Sie und weisen der Variablen iv id = „den numerischen Wert 11 zu. 085c82de67 „>
.
Das heißt: Wenn Sie declare -i foo
sagen, geben Sie der Variablen foo
das Attribut , eine Ganzzahl zu sein.
Das Deklarieren von Zahlen (genau Ganzzahlen, da Bash Dezimalstellen, Gleitkommazahlen und all das immer noch nicht versteht) kann der erste Grund für die Verwendung von declare
, aber das ist nicht der einzige Grund. Wie Sie bereits verstanden haben, können Sie Variablen einige andere Attribute zuweisen. Zum Beispiel können Sie Bash verwenden, um den Wert einer Variablen immer in Großbuchstaben zu schreiben, egal was passiert: Wenn Sie declare -u foo
sagen, dann von da an foo=bar
Bash weist der Variablen foo
tatsächlich die Zeichenfolge BAR
zu.
Um eines dieser Attribute anzugeben Für eine Variable müssen Sie den Befehl declare
verwenden, es gibt keine andere Wahl.
Nun eine andere der Attribute, die Sie über declare
angeben können, sind die berüchtigten Attribute „name-ref“, das Attribut -n
. ( Und jetzt werde ich das Konzept fortsetzen, das ich zuvor auf Eis gelegt habe ).
Das Attribut name-ref ermöglicht Bash-Programmierern im Grunde eine andere Möglichkeit, den Wert zu ändern Dies gibt eine indirekte Möglichkeit, dies zu tun.
Hier ist wie es funktioniert:
Sie declare
eine Variable mit dem Attribut -n
und es ist sehr empfohlen (obwohl nicht unbedingt erforderlich, aber es macht die Sache einfacher), dass Sie dieser sehr Variablen auf derselben declare
Befehl. So:
declare -n baz="foo"
Dies sagt Bash, dass von da an Jedes Mal, wenn Sie den Wert der Variablen mit dem Namen baz
verwenden oder ändern, wird der Wert der Variablen mit dem Namen .
Was bedeutet, dass von da an yo Sie können so etwas wie baz=10+3
sagen, damit foo
den Wert 13 erhält.Vorausgesetzt natürlich, dass foo
zuvor als Ganzzahl (declare -i
) deklariert wurde, wie wir es vor einer Minute getan haben, andernfalls wird die Sequenz abgerufen der vier Zeichen 1
0
+
3
.
Außerdem: Wenn Sie den Wert von foo
direkt ändern, wie in foo=15
, werden Sie sehen 15 auch indem Sie echo “${baz}”
sagen. Dies liegt daran, dass die Variable baz
, die als Namensreferenz von foo
deklariert wurde, immer die Werte von foo
widerspiegelt Wert.
Der obige Befehl declare -n
wird als „Namensreferenz“ bezeichnet, da er die Variable baz
baz
den Wert „foo“ hat, der aufgrund der Option -n
von Bash als Name für behandelt wird eine andere Variable.
Nun, warum auf der Erde möchten Sie das jemals tun?
Nun … es ist erwähnenswert, dass dies eine Funktion für ziemlich fortgeschrittene Anforderungen ist.
In der Tat so fortgeschritten, dass ein Programmierer, wenn er auf ein Problem stößt, das wirklich eine Namensreferenz erfordert, dies auch ist Wahrscheinlich sollte ein solches Problem eher durch die Verwendung einer geeigneten Programmiersprache anstelle von Bash behoben werden.
Eine dieser erweiterten Anforderungen besteht beispielsweise darin, dass Sie als Programmierer dies während der Entwicklung nicht wissen können Welche Variable Sie an einem bestimmten Punkt eines Skripts verwenden müssen, aber zur Laufzeit ist dynamisch vollständig bekannt. Und da es für einen Programmierer nicht möglich ist, zur Laufzeit einzugreifen, besteht die einzige Möglichkeit darin, im Voraus für eine solche Situation im Skript vorzusehen, und eine „Namensreferenz“ kann die einzig praktikable sein Weg. Denken Sie beispielsweise als Plug-Ins an einen Plug-Ins. Der Programmierer eines „Plugin-fähigen“ Programms muss im Voraus generische Vorkehrungen für zukünftige (und möglicherweise Drittanbieter-) Plug-Ins treffen. Daher muss der Programmierer Funktionen wie eine Namensreferenz in Bash verwenden.
Eine weitere erweiterte Anforderung besteht darin, dass Sie mit einer großen Datenmenge im RAM und auch mit Daten umgehen müssen Sie müssen diese Daten an Funktionen Ihres Skripts weitergeben, die auch diese Daten auf dem Weg ändern müssen. In einem solchen Fall könnten Sie diese Daten sicherlich von einer Funktion in eine andere kopieren (wie Bash, wenn Sie dest_var="${src_var}"
ausführen oder wenn Sie Funktionen wie in myfunc "${src_var}"
), aber da diese Daten eine große Menge sind, würde dies zu einer enormen Verschwendung von RAM und für einen sehr ineffizienten Betrieb führen. In solchen Situationen besteht die Lösung darin, nicht eine Kopie der Daten zu verwenden, sondern einen Verweis auf diese Daten. In Bash ein Namensreferenz. Dieser Anwendungsfall ist in jeder modernen Programmiersprache die Norm, aber in Bezug auf Bash ist er ziemlich außergewöhnlich, da Bash hauptsächlich für kurze einfache Skripte entwickelt wurde, die sich hauptsächlich mit Dateien und externen Befehlen befassen, und daher Bash-Skripte selten sehr umfangreich sein müssen Datenmenge zwischen Funktionen. Und wenn die Funktionen eines Skripts einige Daten gemeinsam nutzen müssen (darauf zugreifen und sie ändern müssen), wird dies normalerweise durch die Verwendung einer globalen Variablen erreicht, was in Bash-Skripten ebenso üblich ist wie sehr In den richtigen Programmiersprachen veraltet.
Dann gibt es möglicherweise einen bemerkenswerten Anwendungsfall für Namensreferenzen in Bash, der (möglicherweise ironischerweise) damit verbunden ist, wenn Sie noch andere Arten von Variablen verwenden:
- Variablen, die als „indizierte Arrays“ deklariert sind (
declare -a
) - Variablen, die als „assoziative Arrays“ deklariert sind (
declare -A
).
Dies ist eine Art von Variablen, die einfacher (sowie effizienter) an Funktionen weitergegeben werden können durch die Verwendung von Namensreferenzen anstelle von normalem Kopieren, selbst wenn sie keine großen Datenmengen enthalten.
Wenn all diese Beispiele seltsam und immer noch unverständlich klingen, liegt dies nur daran, dass Namensreferenzen tatsächlich eine sind fortgeschrittenes Thema und eine seltene Notwendigkeit für das typische Verwendungsszenario von B. Asche.
Ich könnte Ihnen von Gelegenheiten erzählen, bei denen ich in Bash Verwendung für Namensreferenzen gefunden habe, aber bisher waren sie hauptsächlich für ziemlich „esoterische“ und komplizierte Bedürfnisse gedacht, und das bin ich Ich fürchte, wenn ich sie beschreiben würde, würde ich die Dinge an diesem Punkt Ihres Lernens nur für Sie komplizieren. Um nur das am wenigsten komplexe (und möglicherweise nicht esoterische) zu erwähnen: Rückgabe von Werten aus Funktionen. Bash unterstützt diese Funktionalität nicht wirklich, daher habe ich das gleiche mithilfe von Namensreferenzen erhalten. Dies ist übrigens genau das, was Ihr Beispielcode tut.
Außerdem ein kleiner persönlicher Rat, der eigentlich besser für einen Kommentar geeignet wäre, aber ich konnte ihn nicht genug verdichten um in die Grenzen des Kommentars von StackExchange zu passen.
Ich denke, das Beste, was Sie im Moment tun sollten, ist, einfach mit Namensreferenzen zu experimentieren, indem Sie die einfachen Beispiele verwenden, die ich gezeigt habe, und möglicherweise mit dem von Ihnen bereitgestellten Beispielcode, ohne Rücksicht darauf im Moment der Teil „Warum auf Erden“ und nur der Teil „Wie es funktioniert“. Wenn Sie ein wenig experimentieren, kann der „Wie“ -Teil besser in Ihren Kopf eindringen, sodass Ihnen der „Warum“ -Teil zu gegebener Zeit klar wird, wenn (oder wenn) Sie ein echtes praktisches Problem haben, für das ein Name- ref wäre wirklich nützlich.
Kommentare
- LL3 Ich mag Ihre Antwort sehr und habe nachgedacht: Ich verstehe endlich, was deklarieren tut – – keine Variablen deklarieren, sondern ihre Attribute deklarieren; Leider habe ich den Überblick verloren, als Sie anfingen zu erklären, was ein Namensreferenz ist. Ich habe keine Ahnung, was es tut und warum ich es verwenden soll.
- Das heißt – warum sollte man dieses Attribut geben
- @JohnDoea, wie ich sehe. Vielleicht verlassen Sie dieses Thema für den Moment. Es ist wahrscheinlich zu früh, um dieses Konzept zum aktuellen Zeitpunkt Ihres Lernens zu verstehen. Wie auch immer, ich habe meine Antwort um weitere Beispiele und einen kleinen persönlichen Nachtrag darüber erweitert, wie Sie vorgehen sollten. Ich habe auch horizontale Linien eingefügt, um die allgemeine Erklärung von
declare
von der spezifischen Erklärung von-n
aus dem persönlichen Nachtrag abzugrenzen. Ich habe auch hier und da ein bisschen umformuliert, aber nichts Wesentliches, also denke ich, dass Sie den Teil-n
plus den kleinen Nachtrag noch einmal lesen können. - Danke, ich denke, ‚ ist okay für mich, dies jetzt zu lernen. Ich brauche nur eine Erklärung, die ich verstehen kann, und ich sollte Ihre gesamte Antwort heute noch einmal lesen ‚ bin hier in der Nähe.
- Sie erwähnen
foo="bar"
unddeclare foo="bar"
. Möglicherweise möchten Sie (wenn auch nur in einer Fußnote) erwähnen, dass in einer Shell-Funktiondeclare foo="bar"
eine lokale Variable undfoo="bar"
eine erstellt globale Variable.
Antwort
Im Allgemeinen declare
in Die bash
-Shell setzt (oder entfernt oder zeigt) Attribute für Variablen. Ein Attribut ist eine Art Anmerkung, die besagt, dass „dies eine Namensreferenz ist“ oder „dies ist ein assoziatives Array“ oder „diese Variable sollte immer als Ganzzahl ausgewertet werden“ oder „diese Variable ist schreibgeschützt und kann nicht zurückgesetzt werden „oder“ diese Variable wird exportiert (eine Umgebungsvariable) „usw.
Die integrierte typeset
ist ein Synonym für declare
in bash
, da typeset
in anderen Shells verwendet wird (ksh
, woher es stammt, und zsh
(zum Beispiel) zum Festlegen von Variablenattributen.
Sehen Sie sich das Namensreferenzbeispiel in genauer an die Frage:
Die Shell-Funktion, die Sie anzeigen, mit einem zusätzlichen Code, der sie verwendet:
#!/bin/bash function read_and_verify { read -p "Please enter value for "$1": " tmp1 read -p "Please repeat the value to verify: " tmp2 if [ "$tmp1" != "$tmp2" ]; then echo "Values unmatched. Please try again."; return 2 else declare -n ref="$1" ref=$tmp1 fi } read_and_verify foo printf "The variable "foo" has the value "%s"\n" "$foo"
Ausführen von:
$ bash script.sh Please enter value for "foo": hello Please repeat the value to verify: hello? Values unmatched. Please try again. The variable "foo" has the value ""
Dies zeigt, dass die Variable foo
nicht auf irgendetwas gesetzt wird, wenn der Benutzer zwei unterschiedliche eingibt Zeichenfolgen.
Dies zeigt, dass die Variable foo
auf die Zeichenfolge gesetzt wird, die der Benutzer eingegeben hat, als er zweimal dieselbe Zeichenfolge eingegeben hat
$foo
erhält den Wert hello
im Hauptteil des Skripts in den folgenden Zeilen in der Shell-Funktion:
declare -n ref="$1" ref=$tmp1
wobei $tmp1
die Zeichenfolge hello
vom Benutzer eingegeben und $1
ist die Zeichenfolge foo
, die über den Hauptteil der Funktion in der Befehlszeile der Funktion übergeben wird Skript.
Beachten Sie, dass die Variable ref
mit declare -n
als Namensreferenzvariable deklariert ist und dass der Wert foo
wird als Wert in dieser Deklaration angegeben. Dies bedeutet, dass von diesem Zeitpunkt an, bis die Variable den Gültigkeitsbereich verlässt, jede Verwendung der Variablen ref
dieselbe ist wie die Verwendung von foo
. Die Variable ref
ist eine Namensreferenzvariable , die an dieser Stelle auf foo
verweist.
Dies hat zur Folge, dass durch Zuweisen eines Werts zu ref
, wie in der Zeile nach der Deklaration, der Wert foo
zugewiesen wird.
Der Wert hello
ist dann in $foo
im Hauptteil des Skripts verfügbar.