Vous pouvez comparer seulement deux nombres avec dccomme:
dc -e "[$1]sM $2d $1<Mp"
... où "$1"est votre valeur maximale et "$2"le nombre que vous imprimeriez s'il était inférieur à "$1". Cela nécessite également GNU dc- mais vous pouvez faire la même chose de manière portable comme:
dc <<MAX
[$1]sM $2d $1<Mp
MAX
Dans les deux cas ci - dessus , vous pouvez définir la précision autre chose que 0 (la valeur par défaut) comme ${desired_precision}k. Pour les deux, il est également impératif de vérifier que les deux valeurs sont bien des nombres car vous dcpouvez effectuer des system()appels avec l' !opérateur.
Avec le petit script suivant (et le suivant), vous devez également vérifier l’entrée - comme grep -v \!|dcun outil permettant de gérer de manière robuste une entrée arbitraire. Vous devez également savoir que dcinterprète les nombres négatifs avec un _préfixe plutôt qu'un -préfixe - car ce dernier est l'opérateur de soustraction.
En plus de cela, avec ce script dc, vous lirez autant de nombres séquentiels \nséparés par ligne électronique que vous voudriez bien le fournir, et vous imprimerez pour chacun votre $maxvaleur ou l'entrée, selon le plus petit des deux:
dc -e "${max}sm
[ z 0=? d lm<M p s0 lTx ]ST
[ ? z 0!=T q ]S?
[ s0 lm ]SM lTx"
Alors ... chacun de ces [carrés bracketing ]étendues est une dc chaîne objet qui est SAved chacun à son réseau respectif - l'une des T, ?ou M. À part quelques petites choses que l’on dcpourrait faire avec une chaîne , elle peut aussi être xutilisée comme une macro. Si vous organisez cela correctement, un petit dcscript entièrement fonctionnel est assemblé de manière assez simple.
dcfonctionne sur une pile . Tous les objets en entrée sont empilés les uns sur les autres - chaque nouvel objet en entrée repoussant le dernier objet en haut et tous les objets en dessous de celui-ci, un par un au fur et à mesure de son ajout. La plupart des références à un objet se rapportent à la valeur de pile supérieure, et la plupart des références insèrent cette pile en haut de la pile (qui extrait tous les objets situés en dessous d'un objet) .
En plus de la pile principale, il y a aussi (au moins) 256 tableaux et chaque élément de tableau est livré avec une pile qui lui est propre. Je n'en utilise pas beaucoup ici. Je stocke simplement les chaînes comme indiqué afin de pouvoir les lutiliser quand bon me semble et les xéchanger sous condition, et j’ai sdéchiré $maxla valeur en haut du mtableau.
Quoi qu'il en soit, ce petit peu dcfait, en grande partie, ce que fait votre script shell. Il utilise l' -eoption GNU-ism - comme dcses paramètres sont généralement pris dans l'entrée standard - mais vous pouvez faire la même chose de la manière suivante:
echo "$script" | cat - /dev/tty | dc
... Si $scriptressemblait à ce qui précède.
Cela fonctionne comme:
lTx- Cela permet d' lexécuter et d' xexécuter la macro stockée dans le haut de T (pour tester, je suppose - je choisis habituellement ces noms de manière arbitraire) .
z 0=?- Test ensuite teste la profondeur de la pile w / zet, si la pile est vide (read: contient 0 objets), elle appelle la ?macro.
? z0!=T q- La ?macro porte le nom de la ? dccommande intégrée qui lit une ligne d’entrée à partir de stdin, mais j’y ai également ajouté un autre ztest de profondeur de la pile, de sorte qu’elle puisse qgérer tout le petit programme s’il affiche une ligne vierge ou atteint EOF. Mais si ce n'est !pas le cas et que la pile est correctement remplie, elle appelle à Tnouveau est.
d lm<M- Test alors va dutiliser le haut de la pile et le comparer à $max (tel que stocké dans m) . Si mest la plus petite valeur, dcappelle la Mmacro.
s0 lm- Maffiche simplement le haut de la pile et le vide dans le scalaire factice 0- juste un moyen peu coûteux de faire éclater la pile. Il a également lOADS à mnouveau avant de revenir à Test.
p- Cela signifie que si mest inférieur au sommet actuel de la pile, il le mremplace (son duplicate, en tout cas) et est ici pimprimé, sinon ce n'est pas le cas et quelle que soit l'entrée, il est pimprimé à la place.
s0- Ensuite (parce pque la pile n'apparaît pas), nous vidons à nouveau le haut de la pile 0, puis ...
lTx- récursive lOAD THNE fois plus de e xecute nouveau.
Ainsi, vous pouvez exécuter ce petit extrait et taper les numéros de manière interactive sur votre terminal et vous dcimprimer le numéro que vous avez entré ou la valeur de $maxsi le nombre que vous avez entré est plus grand. Il accepterait également n'importe quel fichier (tel qu'un tuyau) comme entrée standard. La boucle lecture / comparaison / impression se poursuivra jusqu'à ce qu'elle rencontre une ligne vierge ou une fin de fichier.
Quelques notes à ce sujet, par contre - j’ai écrit ceci uniquement pour émuler le comportement de votre fonction shell, afin qu’il ne gère que de manière robuste le nombre par ligne. dcpeut cependant traiter autant de numéros d'espaces séparés par ligne que vous le souhaitez. Cependant , à cause de sa pile, le dernier chiffre d’une ligne devient le premier sur lequel il opère et, ainsi qu’il est écrit, dcil imprimerait sa sortie en sens inverse si vous imprimiez / tapiez plus d’un nombre par ligne. gérer cela consiste à stocker une ligne dans un tableau, puis à la travailler.
Comme ça:
dc -e "${max}sm
[ d lm<M la 1+ d sa :a z0!=A ]SA
[ la d ;ap s0 1- d sa 0!=P ]SP
[ ? z 0=q lAx lPx l?x ]S?
[q]Sq [ s0 lm ]SM 0sa l?x"
Mais ... je ne sais pas si je veux expliquer cela plus en profondeur. Il suffit de dire que, comme dcchaque valeur de la pile est lue, elle stocke sa valeur ou sa valeur $maxdans un tableau indexé et, une fois détectée, la pile est à nouveau vide, elle affiche ensuite chaque objet indexé avant de tenter d'en lire un autre. ligne d'entrée.
Et alors, alors que le premier script fait ...
10 15 20 25 30 ##my input line
20
20
20
15
10 ##see what I mean?
La seconde fait:
10 15 20 25 30 ##my input line
10 ##that's better
15
20
20 ##$max is 20 for both examples
20
Vous pouvez gérer des flottants de précision arbitraire si vous le définissez d'abord avec la kcommande. Et vous pouvez modifier les radices d' ientrée ou de osortie de manière indépendante - ce qui peut parfois être utile pour des raisons inattendues. Par exemple:
echo 100000o 10p|dc
00010
... qui définit d dc' abord le radix de sortie à 100000, puis en imprime 10.