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

Tout ce qui concerne la programmation.
Répondre
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 997
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : Hors ligne

19 juin 2020, 01:02

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.
Debian testing/stable - XFCE
Avatar du membre
Grhim
Membre très actif
Membre très actif
Messages : 1067
Enregistré le : 30 mai 2016, 01:00
Localisation : Zurich
Status : Hors ligne

19 juin 2020, 01:33

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:
Debian Testing-Sid / Debian Stable / Kali Linux / Gnome3 - KissOs - Raspberry 3b+ -
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 997
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : Hors ligne

19 juin 2020, 10:35

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.
Debian testing/stable - XFCE
Avatar du membre
piratebab
Site Admin
Site Admin
Messages : 3397
Enregistré le : 24 avr. 2016, 18:41
Localisation : sud ouest
Status : Hors ligne

20 juin 2020, 20:26

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 du membre
vv222
Modérateur
Modérateur
Messages : 391
Enregistré le : 18 avr. 2016, 20:14
Localisation : Bretagne
Contact :
Status : Hors ligne

21 juin 2020, 06:38

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 du membre
dezix
Modérateur
Modérateur
Messages : 997
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : Hors ligne

22 juin 2020, 12:22

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:
Debian testing/stable - XFCE
Avatar du membre
dezix
Modérateur
Modérateur
Messages : 997
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : Hors ligne

22 juin 2020, 13:57

@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 ?
Debian testing/stable - XFCE
Avatar du membre
vv222
Modérateur
Modérateur
Messages : 391
Enregistré le : 18 avr. 2016, 20:14
Localisation : Bretagne
Contact :
Status : Hors ligne

22 juin 2020, 17:16

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 du membre
dezix
Modérateur
Modérateur
Messages : 997
Enregistré le : 04 juin 2016, 14:50
Diaspora* : dezix@framasphere.org
Status : Hors ligne

22 juin 2020, 17:53

Merci :good:
Debian testing/stable - XFCE
Répondre