Vous pouvez comparer seulement deux nombres avec dc
comme:
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 dc
pouvez 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 \!|dc
un outil permettant de gérer de manière robuste une entrée arbitraire. Vous devez également savoir que dc
interprè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 \n
séparés par ligne électronique que vous voudriez bien le fournir, et vous imprimerez pour chacun votre $max
valeur 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 S
Aved chacun à son réseau respectif - l'une des T
, ?
ou M
. À part quelques petites choses que l’on dc
pourrait faire avec une chaîne , elle peut aussi être x
utilisée comme une macro. Si vous organisez cela correctement, un petit dc
script entièrement fonctionnel est assemblé de manière assez simple.
dc
fonctionne 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 l
utiliser quand bon me semble et les x
échanger sous condition, et j’ai s
déchiré $max
la valeur en haut du m
tableau.
Quoi qu'il en soit, ce petit peu dc
fait, en grande partie, ce que fait votre script shell. Il utilise l' -e
option GNU-ism - comme dc
ses 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 $script
ressemblait à ce qui précède.
Cela fonctionne comme:
lTx
- Cela permet d' l
exécuter et d' x
exé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=?
- T
est ensuite teste la profondeur de la pile w / z
et, si la pile est vide (read: contient 0 objets), elle appelle la ?
macro.
? z0!=T q
- La ?
macro porte le nom de la ?
dc
commande intégrée qui lit une ligne d’entrée à partir de stdin, mais j’y ai également ajouté un autre z
test de profondeur de la pile, de sorte qu’elle puisse q
gé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 à T
nouveau est.
d lm<M
- T
est alors va d
utiliser le haut de la pile et le comparer à $max
(tel que stocké dans m
) . Si m
est la plus petite valeur, dc
appelle la M
macro.
s0 lm
- M
affiche 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 l
OADS à m
nouveau avant de revenir à T
est.
p
- Cela signifie que si m
est inférieur au sommet actuel de la pile, il le m
remplace (son d
uplicate, en tout cas) et est ici p
imprimé, sinon ce n'est pas le cas et quelle que soit l'entrée, il est p
imprimé à la place.
s0
- Ensuite (parce p
que la pile n'apparaît pas), nous vidons à nouveau le haut de la pile 0
, puis ...
lTx
- récursive l
OAD T
HNE fois plus de e x
ecute nouveau.
Ainsi, vous pouvez exécuter ce petit extrait et taper les numéros de manière interactive sur votre terminal et vous dc
imprimer le numéro que vous avez entré ou la valeur de $max
si 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. dc
peut 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, dc
il 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 dc
chaque valeur de la pile est lue, elle stocke sa valeur ou sa valeur $max
dans 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 k
commande. Et vous pouvez modifier les radices d' i
entrée ou de o
sortie 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.