Jak mogę przypisać dane wyjściowe funkcji do zmiennej za pomocą bash?

100

Mam funkcję bash, która generuje dane wyjściowe:

function scan {
  echo "output"
}

Jak mogę przypisać to wyjście do zmiennej?

to znaczy. VAR = scan (oczywiście to nie działa - sprawia, że ​​VAR jest równy ciągowi „scan”)

Brent
źródło
1
Związane z: stackoverflow.com/q/3236871/435605
AlikElzin-kilaka

Odpowiedzi:

150
VAR=$(scan)

Dokładnie tak samo jak w przypadku programów.

Robert Obryk
źródło
3
Odkryłem, że nowe wiersze są usuwane, gdy wykonałem polecenie „echo $ VAR”. Gdybym zamiast tego zacytował $ VAR, zachował nowe linie.
Brent
2
To nie w 100%. Podstawianie poleceń zawsze usuwa końcowe znaki nowej linii.
TheBonsai
8
To tworzy podpowłokę; czy istnieje sposób, aby to zrobić w tej samej powłoce?
lmat - Przywróć Monikę
24

Możesz używać funkcji bash w poleceniach / potokach, tak jak w normalnych programach. Funkcje są również dostępne dla podpowłok i przejściowo, Zastępowanie poleceń:

VAR=$(scan)

W większości przypadków jest prostym sposobem osiągnięcia pożądanego rezultatu. Poniżej opiszę przypadki szczególne.

Zachowywanie końcowych znaków nowej linii:

Jednym z (zwykle pomocnych) efektów ubocznych zastępowania poleceń jest to, że usuwa dowolną liczbę końcowych znaków nowej linii. Jeśli ktoś chce zachować końcowe znaki nowej linii, może dołączyć fikcyjny znak do wyjścia podpowłoki, a następnie usunąć go za pomocą rozwinięcia parametrów.

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}---"

wydruki (zachowane 3 nowe linie):

output


---

Użyj parametru wyjściowego: unikanie podpowłoki (i zachowanie nowych linii)

Jeśli funkcja stara się „zwrócić” ciąg do zmiennej, przy bash v4.3 i nowszych, można użyć tak zwanego a nameref. Namerefs pozwala funkcji na przyjęcie nazwy jednego lub więcej parametrów wyjściowych zmiennych. Możesz przypisać rzeczy do zmiennej nazwy odniesienia i to tak, jakbyś zmienił zmienną, na którą „wskazuje / odwołuje się”.

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}==="

wydruki:

output

===

Ta forma ma kilka zalet. Mianowicie, pozwala twojej funkcji modyfikować środowisko wywołującego bez używania wszędzie zmiennych globalnych.

Uwaga: użycie nazw odwołań może znacznie poprawić wydajność programu, jeśli funkcje w dużym stopniu opierają się na wbudowanych funkcjach bash, ponieważ unika się tworzenia podpowłoki, która jest wyrzucana zaraz potem. Zwykle ma to większy sens w przypadku małych funkcji często używanych ponownie, np. Funkcji kończących się naecho "$returnstring"

To jest istotne. https://stackoverflow.com/a/38997681/5556676

init_js
źródło
0

Myślę, że init_js powinien używać deklaracji zamiast lokalnego!

function scan3() {
    declare -n outvar=$1    # -n makes it a nameref.
    local nl=$'\x0a'
    outvar="output${nl}${nl}"  # two total. quotes preserve newlines
}
Hamid Reza Hasani
źródło
localwbudowane zaakceptuje żadnych opcji, że declarewbudowane zaakceptuje. z szybkiego testu wygląda również, że declare -nw zakresie funkcji podaje również zmienny lokalny zasięg. wydaje się, że są tutaj wymienne.
init_js