BASH : Nom de variable formé par variable(s) Le sujet est résolu

Tout ce qui concerne la programmation.
Répondre
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

Bonjour,

BASH : Est-il possible d'écrire un nom de variable avec des variables ?

P.ex :

Si j'ai une série de variables avec des noms formés d'une partie commune p ex : var1 ; var2

et une variable test assignée par une autre partie du script avec les valeurs 1 ou 2

echo "var$test"

affiche bien selon la valeur de $test : var1 ou var2




Pour le moment je n'ai trouvé que cette solution utilisant une variable supplémentaire name :

Code : Tout sélectionner

#!/bin/bash
#
read -p 'var1 =  ???  : ' var1 ;
read -p 'var2 =  ???  : ' var2 ;
read -p 'test = 1 ou 2 ???  : ' test ;
name="var$test" ;
echo "$name vaut ${!name}" ;
echo 'fin' ;
exit
${!name} fournit la valeur de la bonne variable

et qui donne :

Code : Tout sélectionner

$ ./test.sh
var1 =  ???  : toto
var2 =  ???  : titi
test = 1 ou 2 ???  : 1
var1 vaut toto
fin


Alors existe-t-il une solution plus directe sans passer par une variable intermédiaire ( comme dans ce qui précède) ?

Dans le style de cette syntaxe (qui ne fonctionne pas) :

Code : Tout sélectionner

$ test=1
$ var1=toto

$ echo $"var$test"
var1

ou

$ echo ${var$test}
bash: ${var$test} : mauvaise substitution
J'en est testé plein d'autres et je n'obtiens jamais : toto


... merci pour votre aide.
**Simple Utilisateur** -- Debian stable - XFCE
Avatar de l’utilisateur
Grhim
Membre très actif
Membre très actif
Messages : 1370
Inscription : 30 mai 2016, 01:00
Localisation : kekparr'par'là
Status : Hors-ligne

dezix a écrit : 19 juin 2020, 01:02 BASH : Est-il possible d'écrire un nom de variable avec des variables ?
..on m'a toujours conseiller de mettre de vrais mots au lieu de nom de variable au cas où a force du code l'on peux ne plus se souvenir de quel est la fonction de la variable a moins de renseigner le tout en commentaire...

allez soyons fou !!! :drinks:
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

Grhim a écrit : 19 juin 2020, 01:33 ..on m'a toujours conseiller de mettre de vrais mots au lieu de nom de variable au cas où a force du code l'on peux ne plus se souvenir de quel est la fonction de la variable a moins de renseigner le tout en commentaire...
Oui, je suis d'accord,
mais cela ne contredit pas la démarche "stratégique" d'avoir dans un script des variables "variables" en fonction du résultat des étapes précédentes.
**Simple Utilisateur** -- Debian stable - XFCE
Avatar de l’utilisateur
piratebab
Site Admin
Site Admin
Messages : 4902
Inscription : 24 avr. 2016, 18:41
Localisation : sud ouest
Status : En ligne

Ca me fait penser à ces programmes qui écrivent tout seul leur propre code, je ne me rappelle plus comment ça s'appelle.
Je pense que si tu en là, c'est qu'a la base tu as mal posé ton problème. Dans une variable, c'est le contenu qui est variable, pas le nom.
Avatar de l’utilisateur
vv222
Membre actif
Membre actif
Messages : 852
Inscription : 18 avr. 2016, 20:14
Contact :
Status : Hors-ligne

On utilise ça chez ./play.it :

Code : Tout sélectionner

# get the value of a variable and print it
# USAGE: get_value $variable_name
get_value() {
	local name
	local value
	name="$1"
	value="$(eval printf -- '%b' \"\$$name\")"
	printf '%s' "$value"
}
source

Un exemple d’utilisation plutôt simple :

Code : Tout sélectionner

architecture=$(get_value "${1}_ARCH")
Et un autre qui pousse le truc un peu plus loin :

Code : Tout sélectionner

DEFAULT_OPTION_PREFIX=$(get_value "DEFAULT_OPTION_PREFIX_$(printf '%s' "$OPTION_PACKAGE" | tr '[:lower:]' '[:upper:]')")
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

vv222 a écrit : 21 juin 2020, 06:38 On utilise ça chez ./play.it 
....

Merci pour le partage de ce bout de code qui fait parfaitement le job :023:


Juste une petite Q?

À quoi correspond le formatage '%s' dans la dernière commande : printf '%s' "$value" ?



Remarque perso (pour les autres débutants)


Il est certain que je n'aurais jamais trouvé ça moi-même,
...connaissant à peine les commandes internes : local ; eval ; printf

cela m'a donné une bonne occasion d'explorer le chapitre des commandes internes de $man bash

c'est ballot comme on se prive des bases par manque de curiosité
et aussi parce que débutant,
les manuels sont si indigestes qu'il faut une bonne dose de maturité
avant d'en extraire la moelle sans chopper un mal de tronche ! :wacko:

Du coup pour vérifier et tester ma compréhension de cette fonction
j'ai fait ce petit script de test :

Code : Tout sélectionner

#!/bin/bash
#
# 
# Script:	get_value.sh 
# Auteur:	dezix 
# Date:		2020-06-21
# Version:	0.1
#
# Fonction:	get_value ()	auteur = vv222
#	source = https://forge.dotslashplay.it/play.it/scripts/-/blob/2.11.4/play.it-2/src/10_common.sh
#
#	Script de test de la fonction
#	-> Affiche la valeur d'une variable (foo1/foo2) sélectionnée en fonction du "test_result"
#
#
##########################
#
####    FONCTION    #############
#
# get the value of a variable and print it
# USAGE: get_value $variable_name
get_value ()
{
	local name ;
	local value ;
	name="$1" ;
	value="$(eval printf -- '%b' \"\$$name\")" ;
	printf '%s' "$value" ;
}
#
####    TEST    ################
#
read -p '1 ou 2 ? : ' test_result ;    # Saisie manuelle du résultat d'un test fictif
foo1='I am foo1' ;                     # Variable à afficher
foo2='I am foo2' ;                     # Variable à afficher
bar="foo$test_result" ;                # Nom de la variable "dynamique" dépendant du test
echo "$bar vaut $(get_value $bar)" ;   # Appel de la fonction comme argument d'une cmde (echo)
echo 'fin' ;                           # Juste pour être certain du bon fonctionnemnt du script 
exit
#
####    SORTIE    ###############
#
#$ ./get_value.sh
#1 ou 2 ? : 1
#foo1 vaut I am foo1
#fin
#
##########################
Voilà ce n'est pas grand-chose
mais ça pourra peut-être débrouiller quelque débutant en script passant par-là

:006:
**Simple Utilisateur** -- Debian stable - XFCE
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

@vv222

Dans ton fichier 10_common.sh la fonction get_value est utilisée dès la 1ère fonction déclarée,
donc avant de déclarer get_value

comment cela peut-il se faire ?
**Simple Utilisateur** -- Debian stable - XFCE
Avatar de l’utilisateur
vv222
Membre actif
Membre actif
Messages : 852
Inscription : 18 avr. 2016, 20:14
Contact :
Status : Hors-ligne

dezix a écrit : 22 juin 2020, 12:22À quoi correspond le formatage '%s' dans la dernière commande : printf '%s' "$value" ?
Le premier argument de printf est le format de la chaîne à afficher, le second la valeur à substituer au "%s" de la chaîne de format. Ce sera probablement plus clair avec un exemple :

Code : Tout sélectionner

printf 'J’aime le %s, surtout quand il est %s.\n' 'café' 'bien corsé'
Cette commande affiche :

Code : Tout sélectionner

J’aime le café, surtout quand il est bien corsé.
---
dezix a écrit : 22 juin 2020, 13:57 Dans ton fichier 10_common.sh la fonction get_value est utilisée dès la 1ère fonction déclarée,
donc avant de déclarer get_value

comment cela peut-il se faire ?
En fait, contrairement à l’impression que tu as eu à la lecture de ce bout de code, get_value n’est pas utilisé avant sa définition. Encore une fois, un exemple sera sûrement plus parlant qu’une explication embrouillée :

Code : Tout sélectionner

#!/bin/sh
set -o errexit

affichage_date() {
	local date
	date=$(recuperation_date)
	printf '%s\n' "$date"
	return 0
}

recuperation_date() {
	date '+%F'
	return 0
}

# La fonction affichage_date et les fonctions dont elle dépend doivent être définies avant cette ligne
affichage_date

exit 0
Dans cet exemple, recuperation_date n’est appelé qu’à la toute fin, au moment où on appelle affichage_date, peu importe l’ordre de déclaration des fonctions.

Au contraire de cet autre exemple, qui lui va bien déclencher une erreur en essayant d’appler recuperation_date avant que cette fonction soit définie :

Code : Tout sélectionner

#!/bin/sh
set -o errexit

affichage_date() {
	local date
	date=$(recuperation_date)
	printf '%s\n' "$date"
	return 0
}

# La fonction affichage_date et les fonctions dont elle dépend doivent être définies avant cette ligne
affichage_date

recuperation_date() {
	date '+%F'
	return 0
}

exit 0
Avatar de l’utilisateur
dezix
Membre hyper actif
Membre hyper actif
Messages : 3546
Inscription : 04 juin 2016, 14:50
Status : Hors-ligne

Merci :good:
**Simple Utilisateur** -- Debian stable - XFCE
Répondre