Bonsoir à tous,
Tout fraîchement inscrit sur ce forum, je sollicite déjà votre aide.. Après avoir chercher pas mal de temps et arpenter plusieurs forums, je ne parviens pas à trouver une solution.
Voilà ma situation:
J'ai crée un script qui affiche la valeur minimum parmis des valeurs passées en paramètre.
#!/bin/sh
nb=$1
while [ $# -ne 0 ]
do
if [ $1 -lt $nb ]
then
nb=$1
shift
else
nb=$nb
shift
fi
done
echo "Le nombre le plus petit des paramètres est $nb"
Seulement voilà, j'aimerais le modifier pour que ces valeurs ne soit plus passer en paramètre mais saisie par l'utilisateur. J'avais penser à la manière suivante:
- read var
- Une boucle for dont i va prendre chaque valeur de var et avec à l'interieur un if qui testera si i est inférieur au terme précédant, avec le code suivant:
#!/bin/sh
read var
nb=99999999
for i in $var
do
if [ $i -lt $nb ]
nb=$i
else
nb=$nb
fi
done
echo " La valeur la plus petite est $nb"
Seulement je suis obliger d'initialiser la variable nb à un très grand nombre.. ce qui est problématique.
Si vous avez une solution je suis preneur :)
Merci d'avance!
# modifie l'initialisation
Posté par Nodeus . Évalué à 3.
Au lieu de d'initialiser nb manuellement
initialise le avec le premier nombre de ta liste saisie par l'utilisateur.
De plus il manque une instruction dans ta structure de contrôle.
Je te laisse chercher laquelle c'est plus formateur :D
[^] # Re: modifie l'initialisation
Posté par Arthur Accroc . Évalué à 6.
Quelle est ta manière simple de récupérer juste le premier élément malgré bash (je dis « malgré », parce que bash, c’est comme Perl en moins puissant mais plus compliqué, même s’il est bien moins indigent que le Bourne shell dont il descend) ?
Parce que je vois l’affectation de toute la liste aux variables $1, $2… avec
(intérêt supplémentaire : on peut ensuite reprendre le script prévu pour traiter les arguments), l’affectation de toute la liste à un tableau avec
(ensuite ${tab[2]} pour accéder par exemple au troisième élément, $tab donnant le premier élément), mais récupérer juste le premier élément, je ne vois pas trop…
À la réflexion, on peut récupérer juste le premier élément avec
Un peu cryptique quand même pour un débutant (enfin c’est du bash…) ; explication : c’est une substitution qui rend le contenu de la variable allégé du premier espace et de tout ce qui suit.
Effectivement.
Par contre, il y a aussi des instructions superflues : nb=$nb, on peut aussi sortir le shift du if then else fi dans le premier script et supprimer le else dans la foulée.
Tant qu’on y est, on peut utiliser && plutôt que if then fi et le contenu de la boucle while (du premier script) se réduit à :
« Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone
[^] # sh
Posté par Arthur Accroc . Évalué à 5.
Ah, je viens de remarquer que le shell utilisé est sh (#!/bin/sh). Du coup, à moins que ce soit bash quand même (c’est le cas sur certaines distributions), pas de tableau.
Les autres solutions doivent fonctionner quand même avec la plupart des sh (/bin/sh n’est pas le même shell suivant la distribution ou le système). Peut-être pas avec le plus indigent (parmi ceux que je connais, celui d’OpenIndiana : un vieux ksh notoirement bogué et en deçà des spécifications POSIX, conservé pour ne pas casser des scripts qui comptent sur son comportement).
Le seul intérêt (mais réel) d’utiliser sh est la portabilité, dans le sens où tout système de type Unix aura un /bin/sh, alors qu’il aura peut-être ksh mais pas bash ou l’inverse. C’est dommage, dans la mesure où les fonctionnalités communes aux shells évolués disponibles sur chaque système sont plus importantes que celles de leurs /bin/sh, mais il n’y a pas de chemin commun pour ces shells évolués.
Pour ma part, dans un environnement que je maîtrise, je fais directement du Perl. Ça m’évite de mauvaises surprises quand les besoins augmentent. Par exemple, dans l’exemple actuel, on se retrouve finalement à devoir traiter des nombres décimaux et on s’aperçoit alors que le shell ne gère que les entiers…
« Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone
[^] # Re: modifie l'initialisation
Posté par Nodeus . Évalué à 2.
bash pu pas bash
ça change pas grand chose la saisie est une chaîne de caractère donc il faut découpé la chaîne. les éléments sont séparé par des espaces donc il faut utiliser les utilitaire pour traiter les chaînes.
donc des utilitaires comme tr cut, sed, etc.
en faisant par exemple :
nb=$( echo "$var" | cut -d' ' -f1 )
en supposant que le premier caractère n'est pas un espace (mais si c'en ai un il suffit de le supprimer avec tr par exemple). et pour un vieux système comme solaris ou hpux par exemple tu utilises des anti-quotes `.
Les utilitaires comme cut tr et sed sont souvent plus rapide à utiliser que les substitutions.
Juste remarque en passant le shell au départ est conçu pour servir de glu aux utilitaires unix.
Sinon d3f4lt semble satisfait de son premier programme qui ne gère que des entiers son problème est d'utiliser une saisie interactive de tous les nombres au début.
Donc je ne réponds dans ce post qu'a ses deux questions :
Comment faire la saisie par l'utilisateur de la suite d'entiers au début du programme ( réponse qu'il a trouvée lui même ).
Et je réponds à sa deuxième interrogation qui est comment éviter d'avoir à initialiser (certe implicite ) nb avec un très grand nombre.
Niveau cryptique ta réponse l'est encore plus sachant
sur la fin ta réponse ( fin de second message )c'est : moi je le fait en perl
C'est un peu hors sujet non ?
peux-tu m'expliquer quelle est ta solution concrète dans ce cas ?
[^] # Re: modifie l'initialisation
Posté par totof2000 . Évalué à 5. Dernière modification le 28 octobre 2018 à 11:04.
Bien compliqué pour séparer des chaines :
Hein ? Les substitutions sont internes au shell alors que les utilitaires sont des appels à des programmes externes, donc nécessitent au moins un fork + exec (et charger la commande du disque vers la mémoire si elle n'y est pas déjà).
[^] # Re: modifie l'initialisation
Posté par Nodeus . Évalué à 2.
C'est pas séparer des chaînes mais sélectionner le premier élément.
et quand je dis plus rapide c'est pas au sens système mais au sens utilisateur concept de flux plus rapide à saisir et à mettre en œuvre.
c'est vrai que dans ce cas la méthode fonctionne mais elle a des limites par exemple il est impossible d'ajouter des paramètre par la suite si le script évolue.
[^] # Re: modifie l'initialisation
Posté par Arthur Accroc . Évalué à 3.
Lapin compris.
C’est suffisamment peu trivial pour mériter d’être explicité à un débutant.
Tu sembles avoir pris ma question pour une critique contre toi, mais c’était une vraie question. J’aurais pour louper un moyen simple d’obtenir le premier élément.
S’il n’y en a pas (tu m’excuseras, j’espère, de ne pas considérer comme simple l’appel à des commandes tierces), c’est par contre encore une tare du shell POSIX.
Bash, lui, supporte de vrais tableaux ; malheureusement, il n’est pas partout (même s’il est sur la plupart des distributions Linux, hormis les mini-distributions basées sur Busybox).
Si on choisit /bin/sh pour la portabilité et qu’on n’est pas sûr de ne pas tomber sur un vieux shell, mieux vaut éviter autant que possible tous les « ajouts modernes », donc utiliser des anti-quotes.
Je n’ai pas dit le contraire ; c’est une digression qui ne s’adresse pas particulièrement à l’auteur de la question, dont je présume que le but est de se familiariser avec le shell. C’est pour ça que je n’ai pas développé.
En shell, tu passes ton temps à essayer d’éviter des écueils (par exemple, les variables interprétées à chaque appel ; si elles peuvent contenir des espaces ou des caractères bizarres, tu as intérêt à les quoter correctement ; je connais un sysadmin pourtant expérimenté qui a effacé un tas de fichiers qu’il n’aurait pas dû à cause de ça) et à contourner les limitations (par exemple, les fonctions ne peuvent pas retourner de valeur hormis un code d’erreur).
Si tu la veux, la voilà :
et tant qu’on y est, l’équivalent en shell (pas tout à fait : la version Perl supporte des nombres décimaux) :
Bon, dans le cas présent, la version shell n’est pas tellement plus compliquée, mais on est dans un cas simple : pas de valeurs pouvant contenir des espaces, pas besoin de plus d’un tableau…
« Le fascisme c’est la gangrène, à Santiago comme à Paris. » — Renaud, Hexagone
[^] # Re: modifie l'initialisation
Posté par Nodeus . Évalué à 1.
Écrivant sur un clavier azerty à ce moment là mon doit a glissé et le O s'est transformé en P.
Il fallait donc comprendre : bash ou pas bash
et Gandalf m'a interdit de le modifier à posteriori
Rappel : sont disponibles dans les distributions gnu/linux des outils comme man et info pour connaître les options des commandes et au pire pour cut par exemple cut --help.
Non ce n'est pas ça, mais la question était clair et circonscrite et ta réponse longue un peu touffue avec des digressions et parfois du hors sujet. :) de plus le bash bashing :) tout le long de tes propos m'a un peu irrité.
J'ai toujours entendu dire : "il n'y a pas de mauvais langage, il n'y a que des mauvais développeurs" et je m'applique cette maxime chaque jours surtout quand j'écris un bug dans un programme.
J'aime beaucoup cette assertion mais elle est infondée le shell à justement été conçu comme un environnement permettant d'utiliser des commandes externes très performantes dans ce qu'elle font c'est la philosophie même du shell être la glu entre diverses commande Unix et c'est sa grande force.
petit article wikipedia https://fr.wikipedia.org/wiki/Shell_Unix
En lisant les livres de Christophe Blaess c'est une chose claire également :
Langages de scripts sous Linux https://www.blaess.fr/christophe/livres/scripts-sous-linux/ celui-ci est épuisé mais ce trouve en occasion.
Scripts shell Linux et Unix https://www.blaess.fr/christophe/livres/scripts-shell-linux-et-unix/
c'est pour celà que quand on fait un script shell il faut tenir compte du contexte. De plus souvent une simple chaîne de caractères suffit pour les usages courants.
Je ne suis pas d'accord avec cette analyse comme la personne qui pose une question est "débutante" elle a pu très bien lire des documentations ou on indique #!/bin/sh sans vraiment noter la signification réelle de cette ligne ou se poser la question.
J'ai croisé un administrateur système débutant deux années d'expérience qui n'écrivait pas de shebang dans ses scripts, et après discussion m'a avoué qu'il ignorait ce détail mais don't act maintenant il l'a appris et ses script n'en sont que meilleurs.
Et personnellement je suis favorable à l'utilisation des fonctionnalités plus récentes disponible que de garder les vielles habitudes ( ce n'ai que mon opinion ).
mais il est important de connaître les anciennes syntaxe pour ne pas être surpris lors de la relecture d'un script.
Cette partie du site est un forum son but est de répondre aux questions.Mais pour les digressions pourquoi ne pas rédiger un journal pour s'adresser à un public plus large ?
Et je suis prêt et heureux d'en discuter avec toi pour une rédaction conjointe si tu le souhaites.
en utilisant les bonnes pratiques en "quotant" systématiquement tes variables tu n'as pas de problème dans 99,9% des cas.
Tu avance ici un élément faux quand tu dis que les fonctions ne renvoient rien d'autre que des code retour.
tu peux très bien leur faire renvoyer ce que tu veux sur la sortie standard.
fais ce petit test ci-dessous.
tu peux affecter ce retour à une variable comme ceci par exemple.
```
mavar=$( mafonction argument1 argument2 )
echo "$mavar"
```comme je te l'ai dit plus haut, je suis ouvert à toute suggestion pour l'écriture d'un journal ou d'une dépêche sur le sujet.
Et pour finir sur une note positive je trouve ta solution en shell fort élégante et robuste :D
Je regrette encore d'avoir été un peu sec dans ma réponse et j'espère que tu en comprendras la raison.
[^] # Re: modifie l'initialisation
Posté par d3f4lt . Évalué à 1. Dernière modification le 28 octobre 2018 à 16:40.
Bonjour @Nodeus,
Merci pour ta réponse, malheureusement après avoir lu les autres réponses j'ai fini par trouver la réponse sans vraiment avoir encore approfondi. Mais je n'aurais jamais trouver "set" seul :)
Je regarde pour l'instruction dans ma structure de contrôle et je reviens vers toi quand j'aurais refait mon script :)
Bonjour @totof2000,
Merci pour ta réponse, la commande "set" est exactement celle que je cherchais pour compléter mon script. En effet, je voulais donner la première valeur de var à ma variable nb plutôt que de lui affecter obligatoirement un très grand nombre. Merci encore. :)
# pourquoi s'embeter
Posté par NeoX . Évalué à 2.
pourquoi faire une boucle de 1 à nb=99999
alors qu'il suffirait d'ajouter un read dans ta boucle "while"
le script quittera quand l'utilisateur va saisir "quit"
[^] # Re: pourquoi s'embeter
Posté par Nodeus . Évalué à 1.
Il me semble que d3f4lt veux que la suite soit saisie par l'utilisateur au début du programme dans son ensemble.
sans avoir d'autre saisie qu'un retour à la ligne pour valider
[^] # Re: pourquoi s'embeter
Posté par NeoX . Évalué à 2.
justement non,
dans son premier exemple, la liste est saisie des le lancement, en parametre au script
et il veut desormais que ce soit saisie au fur et à mesure
donc c'est bien une saisie DANS la boucle qu'il faut faire
[^] # Re: pourquoi s'embeter
Posté par d3f4lt . Évalué à 1.
Bonjour @NeoX,
Merci pour la modification, je vais tester ça de suite et prendre le plus intéressant pour moi. :)
[^] # Re: pourquoi s'embeter
Posté par NeoX . Évalué à 2.
il te faut surtout comprendre les differences entre les codes,
pour pouvoir reutiliser cette connaissance dans des programmes plus complexes ensuite
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.