138 votes

Comment puis-je assigner la sortie d'une fonction à une variable en utilisant bash ?

J'ai une fonction bash qui produit une certaine sortie :

function scan {
  echo "output"
}

Comment puis-je affecter cette sortie à une variable ?

ie. VAR=scan (bien sûr, cela ne fonctionne pas - cela rend VAR égal à la chaîne "scan")

200voto

Robert Obryk Points 473
VAR=$(scan)

Exactement de la même manière que pour les programmes.

37voto

init_js Points 956

Vous pouvez utiliser les fonctions bash dans les commandes/pipelines comme vous le feriez avec des programmes ordinaires. Les fonctions sont également disponibles pour les sous-shells et, de manière transitive, pour la substitution de commandes :

VAR=$(scan)

C'est le moyen le plus direct d'obtenir le résultat souhaité dans la plupart des cas. Je décrirai les cas particuliers ci-dessous.

Préservation des nouvelles lignes de fin de ligne :

L'un des effets secondaires (généralement utile) de la substitution de commande est qu'elle supprime n'importe quel nombre de retours à la ligne. Si l'on souhaite préserver les retours à la ligne, on peut ajouter un caractère fictif à la sortie du sous-shell, et le supprimer ensuite avec l'expansion des paramètres.

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

imprime (3 sauts de ligne conservés) :

output

---

Utiliser un paramètre de sortie : éviter la sous-shell (et préserver les nouvelles lignes)

Si ce que la fonction cherche à faire est de "renvoyer" une chaîne de caractères dans une variable, avec bash v4.3 et plus, on peut utiliser ce qu'on appelle une fonction nameref . Namerefs permet à une fonction de prendre le nom d'un ou plusieurs paramètres de sortie de variables. Vous pouvez assigner des choses à une variable nameref, et c'est comme si vous changiez la variable qu'elle "pointe/référence".

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

des empreintes :

output

===

Ce formulaire présente quelques avantages. Notamment, elle permet à votre fonction de modifier l'environnement de l'appelant sans utiliser partout des variables globales.

Remarque : l'utilisation des références de noms peut améliorer considérablement les performances de votre programme si vos fonctions dépendent fortement des buildins bash, car elle évite la création d'un sous-shell qui est jeté juste après. Cela a généralement plus de sens pour les petites fonctions réutilisées souvent, par exemple les fonctions se terminant par echo "$returnstring"

C'est pertinent. https://stackoverflow.com/a/38997681/5556676

0voto

Je pense que init_js devrait utiliser declare au lieu de local !

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X