#1 Le 23/03/2018, à 20:03
- Nony80
Script BASH, tri par sélection dans tableau
Bonjour à tous,
Dans le cadre de mon apprentissage de bash (une quinzaine de jours actuellement), je dois répondre à un exercice simple sur le papier.
L'objectif est d'intégrer des nombres entiers dans un tableau.
Puis d'en ressortir la note minimale et la note maximale.
En indice, on nous dit d'utiliser le tri par sélection, de cette façon la note minimale et maximale seront aux extrémités.
Donc j'ai commencé mon script de cette façon, j'ai mis les commentaires pour vous montrer ce que j'ai fait et ce que j'aimerais faire.
Ça sera plus parlant je pense.
#!/bin/bash
# script permettant d'entrer des valeurs dans un tableau et d'en ressortir :
# la note minimale
# la note maximale
# On demande à saisir les notes à intégrer à notre tableau s'appellant tableaunote
read -p "Saisir un tableau d'entrier : " -a tableaunote
# on crée la variable monTableau contenant toutes les valeurs du tableau
# on crée la variable totalValeur contenant le nombre d'éléments présents dans le tableau
monTableau=${tableaunote[*]}
totalValeur=${#tableaunote[*]}
# Tant que le nombre d'éléments est supérieur à 0
while [ $totalValeur -gt 0 ]; do
# Pour chaque éléments de mon tableau
# Si le premier élément est plus grand que tous les autres éléments du tableau, alors
# on place le premier élément en tant que dernier élément
# et on décrément de 1 le nombre d'élément total afin de faire la même analyse au tout suivant entre $1 et les autres éléments sauf le dernier élément
# sinon si $1 est plus petit qu'un des autres éléments du tableau alors on passe à l'élément suivant
for element in $monTableau; do
if
totalValeur=$((totalValeur-1))
done
done
Comme vous voyez, je me suis arrêter au while réellement, tout le reste j'en parle en commentaire mais je ne suis même pas convaincu que c'est possible de cette façon.
Par contre SVP, ne m'envoyez pas des liens autres, car j'ai quasiment tout parcouru, j'ai vu des exemples mais non commentés et incompréhensibles à mon niveau.
Pouvez-vous m'aider en m'expliquant ?
Hors ligne
#2 Le 23/03/2018, à 20:19
- Watael
Re : Script BASH, tri par sélection dans tableau
salut,
on reprend depuis le début :
tu as rempli un sac opaque avec un certain nombre de cailloux.
comment fais-tu pour trouver le plus gros ?
ne parlons pas de programmation pour l'instant.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#3 Le 23/03/2018, à 21:06
- Nony80
Re : Script BASH, tri par sélection dans tableau
Salut Watael,
Je prend un cailloux et je le compare à un autre.
Si le premier cailloux est plus gros, je compare avec un autre cailloux.
Si le premier cailloux est plus petit, je garde le deuxième cailloux et le compare avec d'autres cailloux hormis le premier.
Hors ligne
#4 Le 23/03/2018, à 21:27
- lynn
Re : Script BASH, tri par sélection dans tableau
le tri par sélection
Le tri ou la sélection! Le tri est nécessairement une sélection...
«C'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!»
Coluche
Hors ligne
#5 Le 23/03/2018, à 21:28
- Watael
Re : Script BASH, tri par sélection dans tableau
c'est ça.
sommairement :
pour un_caillou dans la sac,
. si il y a un plus_gros_caillou
. alors
. si un_caillou est-plus-gros-que plus_gros_caillou
. alors
. plus_gros_caillou=un_caillou
. finSi
. autrement
. plus_gros_caillou=un_caillou
. finSi
finPour
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#6 Le 23/03/2018, à 21:58
- Nony80
Re : Script BASH, tri par sélection dans tableau
Je comprend ce que tu veux dire mais il me manque des connaissances pour le mettre en place.
Je bloque à :
si il y a un plus_gros_caillou # Ici je ne vois pas comment savoir qui est le plus_gros_caillou
si un_caillou est-plus-gros-que plus_gros_caillou # là encore je ne vois pas comment faire,
...et malheureusement c'est pareil pour le reste.
Dans ce que tu as marqué, je ne vois pas à quel moment les arguments changent de places. :-/
Hors ligne
#7 Le 23/03/2018, à 22:35
- pingouinux
Re : Script BASH, tri par sélection dans tableau
Bonsoir,
Si tu n'as besoin que des valeurs extrêmes, il est inutile de trier tout le tableau.
vmin=premier_element
vmax=premier_element
Parcourir le tableau à partir du deuxième élément
Si element<vmin : Alors vmin=element
Si element>vmax : Alors vmax=element
Hors ligne
#8 Le 23/03/2018, à 22:39
- Watael
Re : Script BASH, tri par sélection dans tableau
en effet, on ne trie pas le tableau : on retient l'élément qui correspond au critère.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#9 Le 24/03/2018, à 00:11
- Nony80
Re : Script BASH, tri par sélection dans tableau
Bonsoir,
Si tu n'as besoin que des valeurs extrêmes, il est inutile de trier tout le tableau.vmin=premier_element vmax=premier_element Parcourir le tableau à partir du deuxième élément Si element<vmin : Alors vmin=element Si element>vmax : Alors vmax=element
Bonsoir pingouinux,
Donc en gros c'est
if $1 < le reste (je ne sais pas comment le représenter)
alors vmin = $1
echo minimal = $1
elif $1 > le reste (je ne sais pas dire non plus)
alors vmax = $1
echo maximal
J'ai un peu de mal à saisir avec ce code comment on peut ressortir le min et max.
Hors ligne
#10 Le 24/03/2018, à 01:11
- Watael
Re : Script BASH, tri par sélection dans tableau
il faut itérer (énumérer) les éléments du tableau dans un boucle for :
pour item dans liste...
cf. help for
tu dois revoir la syntaxe de if.
cf. help if
Attention!
dans le contexte de la commande test, < est un faux-ami (on s'en sert dans du pseudo-code pour faire simple. tu verras plus tard que dans le contexte d'une Évaluation arithmétique, par contre, c'est correct ),
il compare exclusivement des chaînes alphanumériques (du texte), pas des nombres.
cf. help test
pour te faire la main avec les commandes et la syntaxe du shell, tu devrais les expérimenter dans des projets de plus petite importance : faire des tests simples, boucler sur des listes, élaborer des conditions plus complexes...
il faut expérimenter dans la console, n'essaie pas d'écrire un script si tu ne maîtrises pas un minimum les commandes et leur syntaxe.
Dernière modification par Watael (Le 24/03/2018, à 01:17)
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#11 Le 24/03/2018, à 02:15
- Nony80
Re : Script BASH, tri par sélection dans tableau
Je comprend Watael, malheureusement, on ne nous laisse pas le temps.
Je dois rendre ce script avant dimanche soir, en sachant que j'ai un module qui me demande du travail aussi (Mise en place d'un VPN pour une entreprise).
Je vais essayer de trouver.
Merci à vous pour votre aide.
Hors ligne
#12 Le 24/03/2018, à 13:20
- kholo
Re : Script BASH, tri par sélection dans tableau
salut,
une autre façon :
IFS=$'\n' sorted=( $(sort -nr <<<"${unTableau[*]}") )
sort ; -n pour numérique ; -r pour reverse
#!/bin/bash
desElements="13 5 45 12 56 32 87 44 1"
IFS=' ' unTableau=( $desElements )
echo "tous les élements du tableau"
for i in ${unTableau[@]}
do
echo "-> $i"
done
echo "*************************************"
echo "traitement :"
# LA LIGNE EST ICI
IFS=$'\n' sorted=( $(sort -nr <<<"${unTableau[*]}") )
echo "*************************************
tous les éléments dans l'ordre décroissants"
for i in ${sorted[@]}
do
echo "-> $i"
done
echo "*************************************"
echo "le plus grand est le premier élément : ${sorted[0]}"
exit 0
Hors ligne
#13 Le 24/03/2018, à 16:41
- erresse
Re : Script BASH, tri par sélection dans tableau
Donc en gros c'est
if $1 < le reste (je ne sais pas comment le représenter)
alors vmin = $1
echo minimal = $1
elif $1 > le reste (je ne sais pas dire non plus)
alors vmax = $1
echo maximalJ'ai un peu de mal à saisir avec ce code comment on peut ressortir le min et max.
Bonjour Nony80,
Tu as omis un point primordial dans la séquence que t'a indiquée pingouinux :
vmin=premier_element
vmax=premier_element
Il s'agit du chargement de la valeur initiale des variables "vmin" et "vmax".
Une fois ces valeurs initialisées, on ne fait de comparaison que deux à deux, on ne connaît évidemment pas la valeur de la totalité des éléments à un moment T, seulement celles de la valeur courante des variables "vmin" et "vmax", comparées à chaque élément du tableau au cours de la boucle.
Chaque fois que l'élément du tableau est inférieur à "vmin", on remplace la valeur de "vmin" par celle de l'élément du tableau.
Chaque fois que l'élément du tableau est supérieur à "vmax", on remplace la valeur de "vmax" par celle de l'élément du tableau.
À la fin de boucle, on aura forcément la plus petite valeur contenue dans le tableau dans "vmin" et la plus grande dans "vmax".
C'est aussi simple que ça...
Plus de 50 ans d'informatique, ça en fait des lignes de commandes en console, mais on n'avait pas le choix...
Excellente raison pour, aujourd'hui qu'on le peut, utiliser au maximum les INTERFACES GRAPHIQUES !
Important : Une fois résolu, pensez à clore votre sujet en ajoutant [Résolu] devant le titre du 1er message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.
Hors ligne
#14 Le 24/03/2018, à 16:58
- Watael
Re : Script BASH, tri par sélection dans tableau
read min max < <(printf '%s\n' "${array[@]}" | sort -n | sed -n '1h;${H;g;s/\n/ /p}')
?
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#15 Le 24/03/2018, à 17:43
- erresse
Re : Script BASH, tri par sélection dans tableau
C'est un fait, il y a mille façon de faire pour obtenir le même résultat, mais je pense que Nony80 qui essaie de programmer en bash depuis une quinzaine de jours a surtout besoin de comprendre le fonctionnement pas à pas des instructions "de base" pour le moment.
Une commande telle que tu la proposes est certainement très efficace, mais pour le moins hermétique à tout profane qui n'a pas déjà absorbé 10 tomes de documentation sur le shell et le bash, ne crois-tu pas ?
(D'ailleurs, c'était bien ta démarche initiale, avec ton sac de cailloux. On se demande où il est passé dans cette version).
Plus de 50 ans d'informatique, ça en fait des lignes de commandes en console, mais on n'avait pas le choix...
Excellente raison pour, aujourd'hui qu'on le peut, utiliser au maximum les INTERFACES GRAPHIQUES !
Important : Une fois résolu, pensez à clore votre sujet en ajoutant [Résolu] devant le titre du 1er message, et un bref récapitulatif de la solution à la fin de celui-ci. Merci.
Hors ligne
#16 Le 24/03/2018, à 19:20
- Watael
Re : Script BASH, tri par sélection dans tableau
je faisais écho à la réponse de Kholo.
« c'est lui qu'a commencé ! »
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#17 Le 25/03/2018, à 02:08
- Nony80
Re : Script BASH, tri par sélection dans tableau
Salut les gars,
Merci d'avoir continué le topic.
@kholo : ta solution est certainement très bonne mais le temps que je comprenne tous les détails du script, je serais passé à autre chose, je crois. ^^
@ Watael : c'est un beau oneline et je kifferais savoir faire ça en une ligne.
@erresse : merci pour ton explication sur mes doutes, je pense avoir compris du coup, en faite c'est logique en ayant l'explication devant mes yeux.
Je confond boucle et condition, ce qui est assez bête au finale...
Donc je me lance avec tes explications (pas encore testé sur la machine) :
#!/bin/bash
# script permettant d'entrer des valeurs dans un tableau et d'en ressortir :
# la note minimale
# la note maximale
# On demande à saisir les notes à intégrer à notre tableau s'appellant tableaunote
read -p "Saisir un tableau d'entrée : " -a tableaunote
# on crée la variable monTableau contenant toutes les valeurs du tableau
# on crée la variable totalValeur contenant le nombre d'éléments présents dans le tableau
monTableau=${tableaunote[*]}
vmin=${tableaunote[0]}
vmax=${tableaunote[0]}
for element in $monTableau; do
if [ $vmin -gt $element ]; then
vmin=$element
elif [ $vmax -lt $element ]; then
vmax=$element
fi
done
echo "Note minimale" = $vmin
echo "Note maximale" = $vmax
^
Edit : je viens de tester et ça fonctionne. Merci beaucoup, j'ai mis du temps quand même à le mettre en place. Mais je suis content.
Dernière modification par Nony80 (Le 25/03/2018, à 04:02)
Hors ligne
#18 Le 25/03/2018, à 04:17
- Watael
Re : Script BASH, tri par sélection dans tableau
for element in "${tableauNote[@]}"
la variable "plate" monTableau (qui n'est d'ailleurs plus un tableau) ne sert à rien.
Dernière modification par Watael (Le 25/03/2018, à 04:18)
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#19 Le 25/03/2018, à 07:27
- pingouinux
Re : Script BASH, tri par sélection dans tableau
la variable "plate" monTableau (qui n'est d'ailleurs plus un tableau) ne sert à rien.
En fait, "$monTableau" est le premier élément du tableau.
Hors ligne
#20 Le 25/03/2018, à 12:39
- kholo
Re : Script BASH, tri par sélection dans tableau
@Nony80
c'est pas si compliqué que ça
ça repose juste sur les tableaux
et comme tu dois être en train d'apprendre à les gérer
voilà quelques trucs simples.
le premier truc que veut savoir un newbee est comment créer un tableau :
desElements="13 12 26 3 8 45 65"
pour le moment desElements est une chaîne alphanumérique
pour en faire un tableau :
unTableau=( $desElements )
Mais pour être certain que le séparateur est l'espace
IFS=' '
pour que le IFS= ne soit pris QUE pour la ligne : on le met sur la ligne sans séparateur ";"
IFS=' ' unTableau=( $desElements )
NB : $'\n' pour le saut de ligne
pour accèder à tous les éléments on utilise un for sur un tableau NON quotté :
for i in ${unTableau[@]}
do
echo "la valeur est $i"
done
ou par son index :
for ((i=0 ; i<${#unTableau[@]} ; i++))
do
echo "la valeur est ${unTableau[$i]} "
done
explication de la ligne que j'ai choisi :
IFS=$'\n' sorted=( $(sort -nr <<<"${unTableau[*]}") )
tous les éléments d'un tableau unTableau (en texte bout à bout)
"${unTableau[*]}"
est envoyé à
<<<
sort et rangé dans l'ordre numérique inverse
sort -nr
le $() pour exécuter ça à part
$(sort -nr <<<"${unTableau[*]}")
ici les valeurs sont rangée dans l'ordre inverse
mais la sortie de ce code est un ensemble de lignes séparées par des sauts de lignes
donc on recrée un tableau avec le IFS déclaré pour prendre le saut de ligne comme séparateur
IFS=$'\n' ... ( $(du code ici) )
et on met le tout dans une variable sorted qui est un tableau
IFS=$'\n' sorted=( $(du code ici) )
voila...
Hors ligne
#21 Le 25/03/2018, à 12:53
- Watael
Re : Script BASH, tri par sélection dans tableau
En fait, "$monTableau" est le premier élément du tableau.
monTableau=${tableaunote[*]}
ici, monTableau reprend, dans une variable "plate", le contenu ([\*], et non [0]) de tableaunote.
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#22 Le 25/03/2018, à 13:16
- pingouinux
Re : Script BASH, tri par sélection dans tableau
@Watael :
Effectivement, j'ai un peu mélangé les variables monTableau et tableaunote.
Je voulais juste dire
$ tablo=( aaa bbb ccc ddd )
$ echo $tablo
aaa
mais cette remarque était hors de propos.
Hors ligne
#23 Le 25/03/2018, à 13:20
- Watael
Re : Script BASH, tri par sélection dans tableau
effectivement, $tableaunote = ${tableaunote[0]}
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#24 Le 25/03/2018, à 13:53
- Nony80
Re : Script BASH, tri par sélection dans tableau
Salut à vous,
@kholo, merci pour ce détail hyper pédagogique, j'ai compris la majorité des choses que tu as expliqué.
Bon, je ne vais pas te mentir, il va me falloir encore pas mal d'essais et de pratiques avant de maîtriser tout ça.
@watael et @pingouinux : je n'ai pas trop compris votre discussion. ^^
En gros cette ligne :
for element in $monTableau; do
Moi je l'interprète comme : pour chaque élement de tous les éléments de mon tableau.
Vu que j'ai créé la variable
monTableau=${tableaunote[*]}
qui contient toutes les valeurs.
Si c'est une erreur vous auriez mis quoi à la place de $monTableau ?
En tout cas j'ai fait plein d'essais et le script fonctionne correctement.
Hors ligne
#25 Le 25/03/2018, à 14:45
- Watael
Re : Script BASH, tri par sélection dans tableau
tous les éléments du tableau, comme les arguments d'un script, sont rendus disponibles par @ => "${tableau[@]}"
avec des guillemets, il faut toujours mettre des guillemets !
$tableau est équivalent à ${tableau[0]}, càd le premier élément du tableau.
oui, c'est une erreur parce qu'un tableau peut contenir des éléments comportant des espaces :
monTableau=( 'un élément' "un autre élément" et\ un\ autre )
fait quelques essais avec/sans des guillemets, avec @ ou *, en passant par une variable "plate"...
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne