Wie kann ich die Ausgabe einer Funktion mit bash einer Variablen zuordnen?


91

Ich habe eine Bash-Funktion, die eine Ausgabe erzeugt:

function scan {
  echo "output"
}

Wie kann ich diese Ausgabe einer Variablen zuordnen?

dh. VAR = Scan (natürlich funktioniert dies nicht - es macht VAR gleich der Zeichenfolge "Scan")


Antworten:


138
VAR=$(scan)

Genau so wie bei Programmen.


3
Ich entdeckte, dass Zeilenumbrüche entfernt wurden, als ich "$ VAR" wiedergab. Wenn ich stattdessen $ VAR zitierte, wurden die Zeilenumbrüche beibehalten.
Brent

2
Das ist nicht 100% richtig. Durch das Ersetzen von Befehlen werden immer nachfolgende Zeilenumbrüche entfernt.
TheBonsai

6
Dadurch wird eine Unterschale erstellt. Gibt es eine Möglichkeit, dies in derselben Shell zu tun?
Begrenzte Versöhnung

23

Sie können Bash-Funktionen in Befehlen / Pipelines verwenden, da Sie sonst reguläre Programme verwenden würden. Die Funktionen sind auch für Unterschalen und transitiv verfügbar. Befehlsersetzung:

VAR=$(scan)

Ist der einfachste Weg, um in den meisten Fällen das gewünschte Ergebnis zu erzielen. Ich werde im Folgenden Sonderfälle skizzieren.

Beibehaltung nachfolgender Zeilenumbrüche:

Eine der (normalerweise hilfreichen) Nebenwirkungen der Befehlsersetzung besteht darin, dass eine beliebige Anzahl nachfolgender Zeilenumbrüche entfernt wird. Wenn nachgestellte Zeilenumbrüche beibehalten werden sollen, kann ein Dummy-Zeichen an die Ausgabe der Unterschale angehängt und anschließend mit Parametererweiterung entfernt werden.

function scan2 () {
    local nl=$'\x0a';  # that's just \n
    echo "output${nl}${nl}" # 2 in the string + 1 by echo
}

# append a character to the total output.
# and strip it with %% parameter expansion.
VAR=$(scan2; echo "x"); VAR="${VAR%%x}"

echo "${VAR}---"

Drucke (3 Zeilenumbrüche):

output


---

Verwenden Sie einen Ausgabeparameter: Vermeiden der Unterschale (und Beibehalten von Zeilenumbrüchen)

Wenn die Funktion versucht, einen String in eine Variable mit bash v4.3 und höher "zurückzugeben", kann man das verwenden, was als a bezeichnet wird nameref. Mit Namerefs kann eine Funktion den Namen einer oder mehrerer Variablenausgabeparameter übernehmen. Sie können einer nameref-Variablen Dinge zuweisen, und es ist, als hätten Sie die Variable geändert, auf die sie verweist.

function scan3() {
    local -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

VAR="some prior value which will get overwritten"

# you pass the name of the variable. VAR will be modified.
scan3 VAR

# newlines are also preserved.
echo "${VAR}==="

Drucke:

output

===

Diese Form hat einige Vorteile. Es ermöglicht Ihrer Funktion nämlich, die Umgebung des Aufrufers zu ändern, ohne überall globale Variablen zu verwenden.

Hinweis: Die Verwendung von namerefs kann die Leistung Ihres Programms erheblich verbessern, wenn Ihre Funktionen stark von Bash-Buildins abhängen, da die Erstellung einer Subshell vermieden wird, die unmittelbar danach weggeworfen wird. Dies ist im Allgemeinen sinnvoller für kleine Funktionen, die häufig wiederverwendet werden, z. B. Funktionen, die auf endenecho "$returnstring"

Dies ist relevant. https://stackoverflow.com/a/38997681/5556676


0

Ich denke, init_js sollte deklarieren anstelle von lokal verwenden!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}

Das localeingebaute System akzeptiert alle Optionen, die das declareeingebaute System akzeptiert. Aus einem Schnelltest geht auch hervor, dass declare -nin einem Funktionsbereich auch die Variable local scope angegeben ist. es scheint, dass sie hier austauschbar sind.
init_js
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.