Vous n'êtes pas identifié(e).
L'icône rouge permet de télécharger chaque page du wiki visitée au format PDF et la grise au format ODT →
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
utilisateurs:david5647:tutos:bash-fonctions-liste-de-choix-pour-script-interactifs [24/03/2021 00:21] David5647 [Introduction] |
utilisateurs:david5647:tutos:bash-fonctions-liste-de-choix-pour-script-interactifs [24/03/2021 17:53] (Version actuelle) David5647 [Choix parmi liste numérotée] |
||
---|---|---|---|
Ligne 8: | Ligne 8: | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | Collections de fonctions bash pour demande à l'utilisateur de faire un choix parmis une liste et rendre vos scripts plus interactif! | + | Collections de fonctions bash pour demander à l'utilisateur de faire un choix parmi une liste et rendre vos scripts plus interactif! |
- | Liste de choix formaté en colonnes avec choix par défaut (nombre de colonne et choix par défaut optionnel) | + | Les fonctions permettent à chaque fois de définir un choix par défault (si réponse vide ou incorrecte) |
- | <code user>questionWithDefault "Votre choix?" "arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8 arg9 arg10 arg11 arg12 arg13 arg14" -d 8 -c 6 | + | |
- | </code><code> | + | Vous trouverez: |
- | arg1 arg2 arg3 arg4 arg5 arg6 | + | |
- | arg7 arg8 [arg9] arg10 arg11 arg12 | + | |
- | arg13 arg14 | + | |
- | Votre choix? [arg9] : | + | |
- | arg9 | + | |
- | </code> | + | |
- | Liste de choix énumérée et choix par défaut (optionnel) | + | - Question binaire type Oui/Non avec exécution immédiate lors de la réponse de l'utilisateur. |
- | <code user>numberedMenu "Votre choix?" "arg1 arg2 arg3 arg4 arg5" 2 | + | - Choix textuel avec un petit contrôle sur l'affichage |
+ | - Choix dans liste numéroté | ||
+ | |||
+ | Finalement, dans la dernière partie (exemple), vous trouverez un script compilant toutes les fonctions à des fins de démonstration. | ||
+ | |||
+ | **bonus**: pour dé-commenter les scripts: | ||
+ | <code user> cat script.sh | sed '/^\s*#/d' | sed 's/#.*$//' > script_sans commentaires.sh | ||
</code> | </code> | ||
- | <code> | ||
- | 1) arg1 | ||
- | 2) arg2 | ||
- | 3) arg3 | ||
- | 4) arg4 | ||
- | 5) arg5 | ||
- | Votre choix? [2] : | + | ===== Question binaire ===== |
- | arg2</code> | + | |
- | Question oui/non et choix par défaut | + | ==== Utilisation ==== |
- | <code user>askYesNo "Voulez vous continuer ?" true | + | |
- | </code><code> | + | |
- | Voulez vous continuer ? [O/n] o | + | |
- | true</code> | + | |
+ | <file bash askYesNo>askYesNo "Voulez vous continuer ?" true</file> | ||
+ | <code>Voulez vous continuer ? [O/n] o</code> | ||
- | ===== Fonctions ===== | + | ==== Script ==== |
<file bash askyesno.sh> | <file bash askyesno.sh> | ||
#!/bin/bash | #!/bin/bash | ||
- | |||
# Yes/No question with default | # Yes/No question with default | ||
askYesNo () { | askYesNo () { | ||
QUESTION=$1 | QUESTION=$1 | ||
DEFAULT=$2 | DEFAULT=$2 | ||
- | if [ "$DEFAULT" = true ]; then | + | if [ "$DEFAULT" = true ]; then # Valeur par défaut définie en paramètre |
OPTIONS="[O/n]" | OPTIONS="[O/n]" | ||
DEFAULT="o" | DEFAULT="o" | ||
Ligne 56: | Ligne 46: | ||
DEFAULT="n" | DEFAULT="n" | ||
fi | fi | ||
- | read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT | + | read -p "$QUESTION $OPTIONS " -n 1 -s -r INPUT # Execute au premier caractère (-n 1) |
- | INPUT=${INPUT:-${DEFAULT}} | + | INPUT=${INPUT:-${DEFAULT}} # Si $INPUT vide => remplace par $DEFAULT |
echo ${INPUT} | echo ${INPUT} | ||
- | if [[ "$INPUT" =~ ^[yYoO]$ ]]; then | + | if [[ "$INPUT" =~ ^[yYoO]$ ]]; then # True si y,Y,O ou o |
ANSWER=true | ANSWER=true | ||
- | else | + | else # Faux pour le reste |
ANSWER=false | ANSWER=false | ||
fi | fi | ||
Ligne 67: | Ligne 57: | ||
</file> | </file> | ||
- | <file bash split_arguments.sh> | + | |
+ | |||
+ | ===== Choix parmi liste ===== | ||
+ | |||
+ | ==== Utilisation ==== | ||
+ | |||
+ | <file bash fonction questionWithDefaultSimple>questionWithDefaultSimple "Votre choix?" "arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8" arg6</file> | ||
+ | <code> | ||
+ | arg1 arg2 arg3 arg4 | ||
+ | arg5 arg6 arg7 arg8 | ||
+ | Votre choix? [arg6] : </code> | ||
+ | |||
+ | ==== Script ==== | ||
+ | |||
+ | <file bash question_with_default_simple.sh> | ||
#!/bin/bash | #!/bin/bash | ||
- | split_args () { | + | questionWithDefaultSimple () { |
- | POSITIONAL_ARGS="" | + | |
- | NAMED_ARGS="" | + | |
- | PARAM_ARGS="" | + | |
- | while [ $# -gt 0 ] ; do | + | |
- | if [[ "$1" =~ ^- ]]; then | + | # Positional argument should strictly come before named arguments |
- | if ! [[ "$2" =~ ^- ]] && [ -n "$2" ] ; then | + | # 1er argument : Question à poser |
- | NAMED_ARGS="$NAMED_ARGS $1 $2" | + | # 2e argument : Liste des options |
- | shift | + | # 3e argument (optionnel) choix par défaut (sinon le premier item) |
- | else | + | |
- | PARAM_ARGS="$PARAM_ARGS $1" | + | QUESTION=$1 |
- | fi | + | read -ra OPTIONS <<< "$2" # Transforme en array |
- | else | + | |
- | POSITIONAL_ARGS="$POSITIONAL_ARGS $1" | + | if [ -n "$3" ]; then # Si non donnée en entrèe => on prend le premier élément |
- | fi | + | DEFAULT="$3" |
- | shift | + | else |
- | done | + | DEFAULT="${OPTIONS[0]}" |
+ | fi | ||
+ | |||
+ | # Create pattern for printf | ||
+ | COL_SIZE=15 # nombre de caractère pour chaque colonne | ||
+ | FORMAT_STRING="%-${COL_SIZE}s %-${COL_SIZE}s %-${COL_SIZE}s %-${COL_SIZE}s\n" # 4 colonnes de $COL_SIZE caractère (méthode bourrin) | ||
+ | |||
+ | # Show | ||
+ | printf "$FORMAT_STRING" "${OPTIONS[@]}" # Mise en forme des options selon $FORMAT_STRING et affichage | ||
+ | |||
+ | # Ask user | ||
+ | printf "\x1b[1;32m$QUESTION\x1b[0m" # Question en gras + vert | ||
+ | read -p " [$DEFAULT] : " -r INPUT # Demande d'input sans aller à la ligne | ||
+ | INPUT=${INPUT:-${DEFAULT}} # Si l'input est vide, on rempli avec la valeur par défaut | ||
+ | |||
+ | # Collect result | ||
+ | if [[ "${OPTIONS[@]}" =~ "$INPUT" ]]; then # Si la réponse est une réponse valide, c-à-d que la valeur est présente dans $OPTIONS | ||
+ | ANSWER=$INPUT # On garde la valeur dans ANSWER | ||
+ | else | ||
+ | ANSWER=$DEFAULT # Sinon on prend celle par défaut | ||
+ | fi | ||
} | } | ||
+ | </file> | ||
+ | ===== Choix parmi liste : complet ===== | ||
+ | |||
+ | ==== Utilisation ==== | ||
+ | |||
+ | <file bash nom.sh> | ||
+ | questionWithDefaultComplet "Votre choix?" "arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8" -d 4 -c 3 | ||
</file> | </file> | ||
+ | <code> | ||
+ | arg1 arg2 arg3 | ||
+ | arg4 [arg5] arg6 | ||
+ | arg7 arg8 | ||
+ | Votre choix? [arg5] : </code> | ||
+ | |||
+ | ==== Script ==== | ||
- | <file bash question_with_default_complete.sh> | + | <file bash question_with_default_complete> |
#!/bin/bash | #!/bin/bash | ||
- | questionWithDefault () { | + | questionWithDefaultComplet () { |
# Positional argument should strictly come before named arguments | # Positional argument should strictly come before named arguments | ||
+ | # 1er argument : Question à poser | ||
+ | # 2e argument : Liste des options | ||
+ | # -c|--columns (optionnel) Nombre de colonnes pour l'affichage | ||
+ | # -d|--default (optionnel) position dans la liste de l'option à mettre par défaut | ||
QUESTION=$1 | QUESTION=$1 | ||
- | read -ra OPTIONS <<< "$2" # Keep options list | + | read -ra OPTIONS <<< "$2" # Transforme la liste d'options en array |
- | read -ra OPTIONS_SHOW <<< "$2" # Same list but highlight [default value] | + | read -ra OPTIONS_SHOW <<< "$2" # Même liste, mais destinée à être modifié pour l'affichage |
- | POS_DEFAULT=0 # position of default argument | + | POS_DEFAULT=0 # Initialisation : position du choix par défaut à défaut de -d|--default |
- | NB_COLUMNS=4 # nummber of element by line to display | + | NB_COLUMNS=4 # Initialisation ; nombre de colonnes à défaut de paramètre -c|--columns |
- | while [[ $# -gt 0 ]] ; do | + | while [[ $# -gt 0 ]] ; do # Tant que le nombre d'argument ($#) n'est pas épuisé |
- | key="$1" | + | key="$1" # on cherche les clés correspondant aux options (-c et -d) |
case $key in | case $key in | ||
- | -d|--default) | + | -d|--default) # Une fois la clé touvée |
- | POS_DEFAULT="$2" | + | POS_DEFAULT="$2" # On sélectionne l'argument qui lui succède |
- | shift # past argument | + | shift # on "consomme"/retire un argument de la liste $@ |
;; | ;; | ||
- | -c|--columns) | + | -c|--columns) # Même chose pour l'autre clé |
NB_COLUMNS="$2" | NB_COLUMNS="$2" | ||
shift | shift | ||
;; | ;; | ||
esac | esac | ||
- | shift # past value | + | shift # past value # On consomme un argument dans tout les cas |
done | done | ||
# Get new default option and format display | # Get new default option and format display | ||
- | OPTIONS_SHOW[$POS_DEFAULT]="[${OPTIONS_SHOW[$POS_DEFAULT]}]" | + | OPTIONS_SHOW[$POS_DEFAULT]="[${OPTIONS_SHOW[$POS_DEFAULT]}]" # On entoure de [crochet] l'option par défault |
- | DEFAULT="${OPTIONS[$POS_DEFAULT]}" | + | DEFAULT="${OPTIONS[$POS_DEFAULT]}" # On sauve sa valeur dans une variable |
# Get columns character length | # Get columns character length | ||
- | max_length=0 | + | max_length=0 # Calcul de la taille minimum d'une colonne (toutes les options doivent tenir) |
- | for opt in ${OPTIONS[@]}; do | + | for opt in ${OPTIONS[@]}; do # On itère sur les options |
- | opt_length=$(echo $opt | wc -c) | + | opt_length=$(echo $opt | wc -c) # On compte le nombre de caractères |
- | if [ $opt_length -ge $max_length ]; then | + | if [ $opt_length -ge $max_length ]; then # Si on trouve une chaîne plus grande que la précédente "plus grande", |
- | max_length=$opt_length | + | max_length=$opt_length # on enregistre celle nouvelle taille |
fi | fi | ||
done | done | ||
- | max_length=$(($max_length+1)) | + | max_length=$(($max_length+1)) # 'tite marge supplémentaire |
- | # Create pattern for fstring | + | # Create pattern for printf |
- | FORMAT_STRING="" | + | FORMAT_STRING="" # préparation de la mise en forme de l'affichage |
- | for i in $(seq $NB_COLUMNS); do | + | for i in $(seq $NB_COLUMNS); do # On concatène "le nombre de colonnes" * |
- | FORMAT_STRING="$FORMAT_STRING %-${max_length}s " | + | FORMAT_STRING="$FORMAT_STRING %-${max_length}s " # la taille min d'une colonne |
done | done | ||
FORMAT_STRING="$FORMAT_STRING \n" | FORMAT_STRING="$FORMAT_STRING \n" | ||
# Show | # Show | ||
- | printf "$FORMAT_STRING" "${OPTIONS_SHOW[@]}" | + | printf "$FORMAT_STRING" "${OPTIONS_SHOW[@]}" # On affiche |
# Ask user | # Ask user | ||
- | printf "\x1b[1;32m$QUESTION\x1b[0m" | + | printf "\x1b[1;32m$QUESTION\x1b[0m" # Un peu de couleur |
- | read -p " [$DEFAULT] : " -r INPUT | + | read -p " [$DEFAULT] : " -r INPUT # On demande une entrée à l'utilisateur |
- | INPUT=${INPUT:-${DEFAULT}} | + | INPUT=${INPUT:-${DEFAULT}} # Si il n'a rien rentré on substitue la valeur avec celle par défaut. |
# Collect result | # Collect result | ||
- | if [[ "${OPTIONS[@]}" =~ "$INPUT" ]]; then | + | if [[ "${OPTIONS[@]}" =~ "$INPUT" ]]; then # Si la réponse est valide (dans la liste) |
- | ANSWER=$INPUT | + | ANSWER=$INPUT # On garde la valeur |
else | else | ||
- | ANSWER=$DEFAULT | + | ANSWER=$DEFAULT # Sinon, on prend celle par défaut |
fi | fi | ||
} | } | ||
Ligne 160: | Ligne 198: | ||
</file> | </file> | ||
- | <file bash question_with_default_simple.sh> | ||
- | #!/bin/bash | ||
- | questionWithDefaultSimple () { | + | ===== Choix parmi liste numérotée : build-in select ===== |
- | # Positional argument should strictly come before named arguments | + | la build-in select effectue une boucle infinie demandant de choisir parmi une liste, |
+ | vous pouvez insérer une instruction **case** ou un nouveau **select** pour faire des sous menus. | ||
- | QUESTION=$1 | + | === Utilisation === |
- | read -ra OPTIONS <<< "$2" # Keep options list | + | |
- | if [ -n "$3" ]; then | + | <file bash _> |
- | DEFAULT="$3" | + | numberWithSelect "Votre choix?" "arg1 arg2 arg3 arg4 arg5 arg6" |
- | else | + | </file> |
- | DEFAULT="${OPTIONS[0]}" | + | |
- | fi | + | |
- | # Create pattern for fstring | + | <code>Votre choix? |
- | COL_SIZE=15 | + | 1) arg1 |
- | FORMAT_STRING="%-${COL_SIZE}s %-${COL_SIZE}s %-${COL_SIZE}s %-${COL_SIZE}s\n" | + | 2) arg2 |
+ | 3) arg3 | ||
+ | 4) arg4 | ||
+ | 5) arg5 | ||
+ | 6) arg6 | ||
- | # Show | + | #? 5 |
- | printf "$FORMAT_STRING" "${OPTIONS[@]}" | + | Vous avec choisi arg5 |
+ | </code> | ||
- | # Ask user | + | === Script === |
- | printf "\x1b[1;32m$QUESTION\x1b[0m" | + | |
- | read -p " [$DEFAULT] : " -r INPUT | + | <file bash numberWithSelect> |
- | INPUT=${INPUT:-${DEFAULT}} | + | numberWithSelect () { |
+ | | ||
+ | QUESTION=$1 | ||
+ | read -ra OPTIONS <<< "$2" | ||
+ | |||
+ | echo $QUESTION | ||
+ | select ANSWER in ${OPTIONS[@]}; do | ||
+ | if [ -n "$ANSWER" ]; then | ||
+ | echo "Vous avec choisi $ANSWER" | ||
+ | break | ||
+ | else | ||
+ | echo "Il n'y a pas de tel index!" | ||
+ | fi | ||
+ | done | ||
- | # Collect result | ||
- | if [[ "${OPTIONS[@]}" =~ "$INPUT" ]]; then | ||
- | ANSWER=$INPUT | ||
- | else | ||
- | ANSWER=$DEFAULT | ||
- | fi | ||
} | } | ||
+ | |||
</file> | </file> | ||
+ | |||
+ | |||
+ | ===== Choix parmi liste numérotée avec valeur par défaut ===== | ||
+ | |||
+ | ==== Utilisation ==== | ||
+ | |||
+ | <file bash nom.sh> | ||
+ | numberedMenu "Votre choix?" "arg1 arg2 arg3 arg4 arg5 arg6" 2 | ||
+ | </file> | ||
+ | <code> | ||
+ | 1) arg1 | ||
+ | 2) arg2 | ||
+ | 3) arg3 | ||
+ | 4) arg4 | ||
+ | 5) arg5 | ||
+ | 6) arg6 | ||
+ | |||
+ | Votre choix? [2] :</code> | ||
+ | |||
+ | ==== Script ==== | ||
<file bash numbered_menu.sh> | <file bash numbered_menu.sh> | ||
Ligne 202: | Ligne 269: | ||
numberedMenu () { | numberedMenu () { | ||
- | # $1 = question to ask | + | # $1 = Question à poser |
- | # $2 = elements separted by space | + | # $2 = liste des éléments séparés par un espace |
- | # S3 (optionnal) = index of defaut element | + | # S3 (optionnal) = index de l'élément par défaut |
QUESTION=$1 | QUESTION=$1 | ||
- | read -ra OPTIONS <<< "$2" # Keep options list | + | read -ra OPTIONS <<< "$2" # Obtention de la liste de options |
- | if [ -n "$3" ]; then | + | if [ -n "$3" ]; then # Si donné par l'utilisateur (c-à-d variable non vide) |
DEFAULT=$3 | DEFAULT=$3 | ||
- | else | + | else # Sinon, valeur par défaut |
DEFAULT=1 | DEFAULT=1 | ||
fi | fi | ||
Ligne 217: | Ligne 284: | ||
# Show | # Show | ||
printf "\n" | printf "\n" | ||
- | for i in $(seq ${#OPTIONS[@]}); do | + | for i in $(seq ${#OPTIONS[@]}); do # on compte le nombre d'options |
- | printf ' %3s %s\n' "$i)" "${OPTIONS[$(($i-1))]}" | + | printf ' %3s %s\n' "$i)" "${OPTIONS[$(($i-1))]}" # On affiche la position dans la liste et la valeur de l'option |
done | done | ||
printf '\n' | printf '\n' | ||
# ask user | # ask user | ||
- | printf "\x1b[1;32m$QUESTION\x1b[0m" | + | printf "\x1b[1;32m$QUESTION\x1b[0m" # Un peu de couleur (gras + vert) |
- | read -p " [$DEFAULT] : " -r INPUT | + | read -p " [$DEFAULT] : " -r INPUT # Demande valeur sans retour à la ligne |
- | INPUT=${INPUT:-${DEFAULT}} | + | INPUT=${INPUT:-${DEFAULT}} # Substitut par $DEFAULT si réponse vide |
# Collect result | # Collect result | ||
Ligne 263: | Ligne 330: | ||
ANSWER=false | ANSWER=false | ||
fi | fi | ||
- | } | ||
- | |||
- | split_args () { | ||
- | POSITIONAL_ARGS="" | ||
- | NAMED_ARGS="" | ||
- | PARAM_ARGS="" | ||
- | while [ $# -gt 0 ] ; do | ||
- | |||
- | if [[ "$1" =~ ^- ]]; then | ||
- | if ! [[ "$2" =~ ^- ]] && [ -n "$2" ] ; then | ||
- | NAMED_ARGS="$NAMED_ARGS $1 $2" | ||
- | shift | ||
- | else | ||
- | PARAM_ARGS="$PARAM_ARGS $1" | ||
- | fi | ||
- | else | ||
- | POSITIONAL_ARGS="$POSITIONAL_ARGS $1" | ||
- | fi | ||
- | shift | ||
- | done | ||
} | } | ||