Was ist "deklarieren" in Bash?

12

Nachdem ich ilkkachus Antwort auf diese Frage gelesen hatte, erfuhr ich von der Existenz der eingebauten declare(mit Argument -n) Shell.

help declare bringt:

Legen Sie Variablenwerte und Attribute fest.

Deklarieren Sie Variablen und geben Sie ihnen Attribute. Wenn keine NAMEs angegeben sind, zeigen Sie die Attribute und Werte aller Variablen an.

-n ... macht NAME zu einem Verweis auf die Variable, die durch ihren Wert benannt ist

Ich bitte um eine allgemeine Erklärung mit einem Beispiel bezüglich, declareweil ich das nicht verstehe man. Ich weiß, was eine Variable ist und erweitere sie, aber ich vermisse immer noch das manon declare(variable Attribut?).

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
}

quelle

Antworten:

4

In den meisten Fällen reicht es mit einer impliziten Deklaration in bash

asdf="some text"

Manchmal möchten Sie jedoch, dass der Wert einer Variablen nur eine Ganzzahl ist (für den Fall, dass er sich später sogar automatisch ändert, kann er nur in eine Ganzzahl geändert werden, in einigen Fällen standardmäßig auf Null) und kann Folgendes verwenden:

declare -i num

oder

declare -i num=15

Manchmal möchten Sie Arrays, und dann brauchen Sie declare

declare -a asdf   # indexed type

oder

declare -A asdf   # associative type

Gute Tutorials zu Arrays finden bashSie beispielsweise, wenn Sie im Internet mit der Suchzeichenfolge 'bash array tutorial' (ohne Anführungszeichen) surfen

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

  • macht in einer Funktion declaredie Variable lokal (in der Funktion)
  • ohne Namen werden alle Variablen aufgelistet (in der aktiven Shell)

    declare

Schließlich erhalten Sie eine kurze Zusammenfassung der Funktionen des declarein bashden Befehl integrierten Shell- Befehls

help declare
Sudodus
quelle
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 dafür user:murugestimmt wurde, die Bearbeitung abzulehnen. Bitte beachten Sie, dass ich und Muru in den verschiedenen Abschnitten dieser Website mehrmals "zusammengestoßen" sind und ich davon ausgehe, dass seine Ablehnung nicht objektiv ist und im Gegensatz zu den direkten Änderungen, die auf der Seite mit den Bearbeitungsvorschlägen hier vorgestellt werden, tatsächlich schädlich ist: 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.
Sudodus
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 sie vorher nicht ehrlich gesehen) und dass Sie erwogen haben, zumindest einige meiner Änderungen in Ihre Antwort einzufügen. Ich respektiere so viel,
13

Die Ausgabe von help declareist ziemlich knapp. Eine klarere Erklärung findet sich in man bashoder info bash- letztere 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 a bezeichnet wird name. Eine Variable hat einen Wert und null oder mehr Attribute . Attribute werden mit dem declareeingebauten Befehl zugewiesen ...

Und über das 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 jedem Namen den Namen Attribut und machen Sie ihn zu einem Namensverweis auf eine andere Variable. Diese andere Variable wird durch den Wert von name definiert . Alle Verweise, Zuweisungen und Attributänderungen am Namen , mit Ausnahme derjenigen, die das -nAttribut selbst verwenden oder ändern , werden für die Variable ausgeführt, auf die durch den Wert des Namens verwiesen wird . ...

Beachten Sie, dass Namensreferenzvariablen nur in Bash 4.3 oder höher verfügbar sind 1 .

Auch für eine nützliche Einführung in declare und Variablenattribute in Bash möchte ich Sie auf diese Antwort auf "Was tun declare nameund declare -gtun?" Verweisen (die sich jedoch hauptsächlich auf den Umfang der Variablen konzentriert).


Grundsätzlich 2 , declare name=[value]entspricht der Zuordnung name=[value]Sie wahrscheinlich vertraut sind. In beiden Fällen namewird der Nullwert zugewiesen, wenn er valuefehlt.

Beachten Sie, dass dies etwas anders declare nameist festgelegt die Variable name3 :

$ 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 namesein:

  • erklärt und nicht gesetzt , danach declare name;
  • deklariert und gesetzt mit null als Wert, nach name=oder declare name=;
  • deklariert , gesetzt und mit a Wert ungleich Null nach name=valueoder declare name=value.

Allgemeiner, declare [options] name=value

  1. erstellt die Variable name - dies ist ein Parameter mit einem Namen, der wiederum nur ein Teil des Speichers ist, den Sie zum Speichern von Informationen verwenden können 4 ;
  2. weist ihm den Wert valuezu;
  3. Optional können namedie Attribute festgelegt werden, die sowohl die Art des Werts definieren, den gespeichert werden können (nicht in Bezug auf einen Typ) streng genommen , da Bashs Sprache nicht typisiert ist), als auch die Art und Weise, wie er manipuliert werden kann.

Attribute lassen sich wahrscheinlich anhand eines Beispiels leichter erklären: using declare -i namesetzt das Attribut "integer" von nameund lässt es als Ganzzahl behandelt werden. unter Angabe des Handbuchs "wird eine arithmetische Auswertung durchgeführt, wenn der Variablen ein Wert zugewiesen wird":

## 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 des oben Gesagten geschieht in ilkkachus Code Folgendes:

  1. Eine Variable refmit dem Namen "nameref" und dem Inhalt von wird deklariert$1 (dem ersten Positionsargument) wird ihr zugewiesen:

    declare -n ref="$1"

    Das Ziel einer Namensreferenzvariablen refist es, den Namen einer anderen Variablen zu speichern, 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 um eine bequeme Möglichkeit zum Verweisen (und Manipulieren) darauf bereitzustellen. (Nicht die einzige: Indirektion ist eine Alternative; siehe Shell-Parametererweiterung ).

  2. Wenn der Wert der Variablen tmp1zugewiesen istref :

    ref=$tmp1

    Eine zusätzliche Variable, deren Name der Wert von ist ref, wird implizit deklariert. Der Wert von tmp1wird auch indirekt der implizit deklarierten Variablen durch diese explizite Zuordnung zu zugewiesen ref.

Rufen Sie im Kontext Ihrer verknüpften Frageread_and_verify als auf

read_and_verify domain "Prompt text here..."

deklariert die Variable domainund weist ihr den Wert von tmp1(dh die Benutzereingabe) zu. Es wurde genau entwickelt, um den Code, der mit dem Benutzer interagiert, wiederzuverwenden und eine nameref-Variable zum Deklarieren domainund einige andere Variablen zu nutzen.

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 die neueste Version) mit Bash 4.2 ausgeliefert .

2 Wie bei Shell-Builtins üblich, eine erschöpfende und Erklärung 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 als außerhalb des Rahmens dieser Antwort aufzulisten, zu erfassen und zu entfernen.

3 Dieses Verhalten von declare -pwurde in Bash 4.4 eingeführt. Referenz: Datei CHANGES , Abschnitt "3. Neue Funktionen in Bash", Punkt "f".
Wie G-Man in den Kommentaren hervorhob, declare name; declare -p nameliefert Bash 4.3 einen Fehler. Sie können jedoch weiterhin überprüfen, ob dies namevorhanden istdeclare -p | grep 'declare -- name' .

4 FullBashGuide, Parameter auf mywiki.wooledge.org

fra-san
quelle
(1) Ich kann die Ergebnisse, die Sie in Ihrem ersten Codeblock anzeigen, nicht reproduzieren: declare namegefolgt von den Ergebnissen declare -p name"bash: declare: name: not found". (Obwohl declare -p | grep naAusbeuten declare -- name.) (2) Ich glaube, dass es ein wenig irreführend ist, echo "${name-isunset}"im Kontext von declare namedarzustellen, da eine nicht deklarierte (dh nicht definierte) Variable genauso behandelt wird wie eine  deklarierte, aber nicht  gesetzte Variable. (3) Möglicherweise möchten Sie erwähnen, dass namerefs nur in Bash-Version 4.3 und höher verfügbar sind.
G-Man sagt "Reinstate Monica"
@ G-Man Danke für deine Bemerkungen! Ich werde sie so schnell wie möglich ansprechen und meine Antwort gegebenenfalls aktualisieren. Was (1) GNU bash, version 5.0.7(1)-release (x86_64-pc-linux-gnu)betrifft, liefert mein unter Arch Linux immer noch die Ergebnisse, die ich gezeigt habe. Vielleicht wurde dieses Verhalten erst kürzlich eingeführt, das werde ich untersuchen.
-San
Ja; Ich benutze nur Version 4.3.
G-Man sagt 'Reinstate Monica'
1
@ G-Man Antwort aktualisiert mit Anmerkungen zu (1) und (3). Über (2): Ich wollte veranschaulichen, dass declare xdies nicht der Fall ist x, während dies der declare x=Fall ist. Ich konnte keinen Hinweis finden, der die Behauptung stützt, dass declare -- x(als Ausgabe von declare -p x) "nicht gesetzt" declare -- x=""bedeutet , während "gesetzt" bedeutet; Daher habe ich die ${parameter-word}Erweiterung eingeführt, auch wenn sie nicht zwischen "nicht gesetzt" und "nicht vorhanden" unterscheiden kann, wie Sie betonen. Ich bin mir jedoch nicht sicher, wie ich dies in meiner Antwort klarstellen kann (ohne den Leser vom Punkt abzulenken).
Fra-San
7

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., sodass ich nur einige Hintergrundkenntnisse überfliege, die andernfalls einen tieferen Fokus erfordern würden.

Zunächst möchte ich sagen, dass der Befehl auf seiner grundlegendsten Ebene declarenur eine Möglichkeit ist, Bash mitzuteilen, dass Sie einen variablen Wert benötigen (dh einen Wert, der sich während der Skriptausführung möglicherweise ändert) und auf den Sie verweisen Dieser Wert verwendet einen bestimmten Namen, genau den Namen, den Sie neben dem angebendeclare Befehl selbst .

Das ist:

declare foo="bar"

teilt Bash mit, dass die benannte Variable fooden Wert haben sollbar .

Aber ... Moment mal ... wir können das tun, ohne es zu benutzen declare, oder? Wie in:

foo="bar"

Sehr richtig.

Nun, es kommt vor, dass die obige einfache Zuordnung tatsächlich implizit ist Weg eine Variable zu deklarieren.

( Es kommt auch vor, dass das Obige eine der wenigen Möglichkeiten ist, den Wert der genannten Variablen zu ändern. In der fooTat ist es genau der direkteste, präziseste, offensichtlichste und direkteste Weg. Aber es ist nicht der einzige. Ich werde später darauf zurückkommen. ).

Aber dann, wenn es so gut möglich ist, einen "Namen, der der Kürze halber Variablenwerte markiert" (der Kürze halber nur "Variable") zu verwenden, ohne ihn zu verwenden declare  deklarieren, warum sollten Sie diese pompöse "Deklaration" niemals verwenden? " Befehl ?

Die Antwort liegt in der Tatsache, dass die oben implizite Art, eine Variable zu deklarieren (foo="bar" ) , implizit dazu führt, dass Bash die Variable des Typs betrachtet, 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.

Aber Sie als Programmierer müssen manchmal lieber eine Variable als z. B. eine Zahl betrachten, für die Sie arithmetische Operationen ausführen müssen. Wenn Sie eine implizite Deklaration wie verwenden, foo=5+6 wird Bash nicht den Wert 11 zuweisen, foowie Sie möchten erwarten von. Es wird eher fooder Reihenfolge der drei Zeichen zugewiesen 5 + 6.

Also ... Sie müssen Bash mitteilen, dass Sie foo als Zahl und nicht als Zeichenfolge betrachtet werden möchten . Dafür ist eine explizite Funktion declare nützlich.

Sag nur:

declare -i foo=5+6  # <<- note the '-i' option: it means 'integer'

und Bash erledigt gerne die Mathematik für Sie und weist der Variablen den numerischen Wert 11 zu foo.

Das heißt: Indem declare -i fooSie sagen, dass Sie der Variablen foodas Attribut einer Ganzzahl geben.

Das Deklarieren von Zahlen (genau ganze Zahlen, da Bash Dezimalstellen, Gleitkommawerte und all das immer noch nicht versteht) ist möglicherweise der erste Grund für die Verwendung declare, aber 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 sagen declare -u foo, dann, wenn Sie sagen , dass foo=barBash BARder Variablen tatsächlich die Zeichenfolge zuweistfoo .

Um einer Variablen eines dieser Attribute zuzuweisen, müssen Sie den declareBefehl verwenden. Es gibt keine andere Wahl.


Eines der Attribute, die Sie durchgeben können, declareist das berüchtigte "Name-Ref" -n-Attribut , das Attribut. ( Und jetzt werde ich das Konzept wieder aufnehmen, das ich zuvor auf Eis gelegt habe ).

Das Attribut name-ref ermöglicht Bash-Programmierern grundsätzlich eine andere Möglichkeit, den Wert einer Variablen zu ändern. Genauer gesagt gibt es einen indirekten Weg, dies zu tun.

So funktioniert es:

Sie haben declareeine Variable mit dem -nAttribut, und es wird sehr empfohlen (obwohl dies nicht unbedingt erforderlich ist, aber es vereinfacht die Sache), dass Sie dieser Variablen mit demselben declareBefehl auch einen Wert geben . So was:

declare -n baz="foo"

Dies teilt Bash mit, dass von nun an jedes Mal, wenn Sie den Wert der genannten Variablen verwenden oder ändern, der Wert der genannten Variablen baztatsächlich verwendet oder geändert wird foo.

Was bedeutet, dass Sie von nun an so etwas wie sagen können baz=10+3, fooum den Wert 13 zu erhalten. Angenommen, dies foowurde zuvor declare -iwie vor einer Minute als integer ( ) deklariert , andernfalls wird die Sequenz der vier erhalten Zeichen 1 0 + 3.

Außerdem: Wenn Sie fooden Wert direkt ändern , wie in foo=15, sehen Sie 15 auch, indem Sie sagen echo “${baz}”. Dies liegt daran, dass bazdie als name-ref von deklarierte Variable fooimmer fooden Wert widerspiegelt .

Der obige declare -nBefehl wird als "Namensreferenz" bezeichnet, da sich die Variable baz auf den Namen einer anderen Variablen bezieht . Tatsächlich haben wir angegeben, baz dass der Wert "foo" ist, der aufgrund der -nOption von Bash als Name für eine andere Variable behandelt wird.

Nun, warum auf der Erde würden Sie jemals das tun wollen?

Nun ... es ist erwähnenswert, dass dies eine Funktion für ziemlich fortgeschrittene Bedürfnisse ist.

In der Tat so weit fortgeschritten, dass, wenn ein Programmierer mit einem Problem konfrontiert ist, das wirklich eine Namensreferenz erfordern würde, es wahrscheinlich ist, dass ein solches Problem eher durch die Verwendung einer geeigneten Programmiersprache anstelle von Bash behoben werden sollte.

Einer dieser erweiterten Bedürfnisse ist, zum Beispiel, wenn Sie als Programmierer, können nicht während der Entwicklung wissen , welche Variablen , die Sie in einem bestimmten Punkt eines Skripts verwenden, aber es wird voll dynamisch zur Laufzeit bekannt sein. Und da es für einen Programmierer nicht möglich ist, zur Laufzeit einzugreifen, besteht die einzige Möglichkeit darin, im Voraus eine solche Situation im Skript vorzusehen, und ein „Namensreferenz“ kann der einzig praktikable Weg sein. 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 Einrichtungen wie eine Namensreferenz in Bash verwenden.

Eine andere erweiterte Notwendigkeit ist , wenn Sie mit großen Datenmengen zu tun haben , in RAM und Sie auch , dass die Daten um Funktionen des Skripts übergeben müssen , dass auch , dass die 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 es Bash tut, wenn Sie dies tun dest_var="${src_var}"oder wenn Sie Funktionen wie in aufrufen myfunc "${src_var}"), aber wenn diese Daten eine große Menge sind, würde dies zu einer enormen Verschwendung von RAM und zu einer sehr großen Menge führen ineffizienter Betrieb. In solchen Situationen besteht die Lösung darin, keine Kopie der Daten, sondern eine Referenz zu verwendenzu diesen 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 durchaus üblich ist, da es in den richtigen Programmiersprachen sehr veraltet ist.

Dann kann es einen bemerkenswerten Anwendungsfall für Namensreferenzen in Bash geben, der (möglicherweise ironischerweise) damit verbunden ist, wenn Sie noch andere Arten von Variablen verwenden:

  1. Variablen, die als "indizierte Arrays" deklariert sind ( declare -a)
  2. Variablen, die als "assoziative Arrays" deklariert sind ( declare -A).

Hierbei handelt es sich um eine Art von Variablen, die möglicherweise einfacher (und auch effizienter) an Funktionen weitergegeben werden können, indem Namensreferenzen anstelle von normalem Kopieren verwendet werden, selbst wenn sie keine großen Datenmengen enthalten.

Wenn all diese Beispiele seltsam und immer noch unverständlich klingen, dann nur, weil Namensreferenzen in der Tat ein fortgeschrittenes Thema sind und das typische Verwendungsszenario von Bash selten benötigt wird.

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 ich befürchte, dass ich sie nur beschreiben würde, wenn ich sie beschreiben würde Kompliziere die Dinge für dich an diesem Punkt deines Lernens. 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 vielleicht mit dem von Ihnen bereitgestellten Beispielcode, wobei Sie den Teil „Warum um alles in der Welt“ für den Moment außer Acht lassen und sich nur darauf konzentrieren 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.

LL3
quelle
LL3 Ihre Antwort gefällt mir sehr gut und ich habe mir überlegt: Endlich verstehe ich, was deklarieren bedeutet - 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 ist - warum sollte man dieses Attribut geben
@ JohnDoea Ich verstehe. 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 gesetzt, um die allgemeine Erklärung declarevon der spezifischen Erklärung von -naus dem persönlichen Nachtrag abzugrenzen . Ich habe auch hier und da ein bisschen umformuliert, aber nichts Wesentliches, also denke ich, dass Sie den -nTeil und den kleinen Nachtrag einfach noch einmal lesen können .
LL3
Vielen Dank, ich denke, es 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. Ich bin hier.
1
Sie erwähnen foo="bar"und declare foo="bar". Möglicherweise möchten Sie (wenn auch nur in einer Fußnote) erwähnen, dass in einer Shell-Funktion declare foo="bar"eine lokale Variable und foo="bar" eine globale Variable erstellt werden.
G-Man sagt "Reinstate Monica"
6

Im Allgemeinen werden declarein der bashShell Attribute für Variablen festgelegt (oder entfernt oder angezeigt) . Ein Attribut ist eine Art Annotation, die besagt: "Dies ist eine Namensreferenz" 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.

Das typeseteingebaute ist ein Synonym für declarein bash, wie typesetes in anderen Shells ( kshwo es entstanden ist und zshzum Beispiel) zum Festlegen von Variablenattributen verwendet wird.


Schauen Sie sich das Namensreferenzbeispiel in der Frage genauer an:

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"

Führen Sie dies aus:

$ bash script.sh 
Bitte geben Sie den Wert für 'foo' ein: hallo 
Bitte wiederholen Sie den Wert, um zu überprüfen: hallo?
Werte unübertroffen. Bitte versuche es erneut.
Die Variable "foo" hat den Wert ""

Dies zeigt, dass die fooVariable auf nichts gesetzt wird, wenn der Benutzer zwei verschiedene Zeichenfolgen eingibt.

$ bash script.sh 
Bitte geben Sie den Wert für 'foo' ein: hallo 
Bitte wiederholen Sie den Wert, um zu überprüfen: hallo
Die Variable "foo" hat den Wert "hallo"

Dies zeigt, dass die Variable fooauf die Zeichenfolge gesetzt wird, die der Benutzer eingegeben hat, als er dieselbe Zeichenfolge zweimal eingegeben hat .

Der $fooWert helloim Hauptteil des Skripts wird durch die folgenden Zeilen in der Shell-Funktion ermittelt:

declare -n ref="$1"
ref=$tmp1

Dabei $tmp1handelt es sich um die hellovom Benutzer eingegebene Zeichenfolge und $1die Zeichenfolge, foodie in der Befehlszeile der Funktion vom Hauptteil des Skripts übergeben wird.

Beachten Sie, dass die refVariable mit declare -neiner Namensreferenzvariablen deklariert wird und dass der Wert fooals Wert in dieser Deklaration angegeben wird. Dies bedeutet, dass von diesem Zeitpunkt an, bis die Variable den Gültigkeitsbereich verlässt, jede Verwendung der Variablen refdieselbe ist wie die Verwendung foo. Die Variable refist eine Namensreferenzvariable, auf die fooan dieser Stelle verwiesen wird.

Dies hat zur Folge, dass durch Zuweisen eines Werts zu ref, wie in der Zeile nach der Deklaration, der Wert zugewiesen wird foo.

Der Wert helloist dann im $fooHauptteil des Skripts verfügbar .

Kusalananda
quelle