Você pode comparar apenas dois números com os seguintes dc:
dc -e "[$1]sM $2d $1<Mp"
... onde "$1"está seu valor máximo e "$2"é o número que você imprimiria se for menor que "$1". Isso também requer o GNU dc- mas você pode fazer o mesmo de maneira portável:
dc <<MAX
[$1]sM $2d $1<Mp
MAX
Em ambos os casos acima, você pode definir a precisão para algo diferente de 0 (o padrão) como ${desired_precision}k. Para ambos, também é imperativo que você verifique se os dois valores são definitivamente números, pois dcpodem fazer system()chamadas com o !operador.
Com o pequeno script a seguir (e o próximo), você deve verificar a entrada também - grep -v \!|dcou algo assim - para lidar com entrada arbitrária de maneira robusta. Você também deve saber que dcinterpreta números negativos com um _prefixo em vez de um -prefixo - porque o último é o operador de subtração.
Além disso, com esse script, dcvocê lerá o número sequencial de \nnúmeros de linha de ew que você gostaria de fornecê-lo e imprimirá para cada um o seu $maxvalor ou a entrada, dependendo de qual é o menor dos dois:
dc -e "${max}sm
[ z 0=? d lm<M p s0 lTx ]ST
[ ? z 0!=T q ]S?
[ s0 lm ]SM lTx"
Então ... cada um desses [colchetes quadrados ]extensões é uma dc seqüência de objeto que é SAVED cada um para seu respectivo array - qualquer um dos T, ?ou M. Além de algumas outras coisas que dcpodem fazer com uma string , ela também pode ser xreproduzida como uma macro. Se você acertar, um pequeno dcscript totalmente funcional será montado com bastante simplicidade.
dctrabalha em uma pilha . Todos os objetos de entrada são empilhados, cada um sobre o último - cada novo objeto de entrada pressionando o último objeto superior e todos os objetos abaixo dele na pilha por um à medida que são adicionados. A maioria das referências a um objeto são para o valor superior da pilha, ea maioria das referências pop que topo da pilha (que puxa todos os objetos abaixo-lo por um) .
Além da pilha principal, também existem (pelo menos) 256 matrizes e cada elemento da matriz vem com uma pilha própria. Eu não uso muito disso aqui. Eu apenas guardo as strings conforme mencionado para poder lcarregá-las quando desejado e xcalculá-las condicionalmente, e srasguei $maxo valor na parte superior da mmatriz.
Enfim, esse pouco dcfaz, em grande parte, o que o seu shell-script faz. Ele usa a -eopção GNU-ism - como dcgeralmente tira seus parâmetros do padrão - mas você pode fazer o mesmo como:
echo "$script" | cat - /dev/tty | dc
... se $scriptparecia com a parte acima.
Funciona como:
lTx- Isso lapaga e faz xeco da macro armazenada no topo T (para teste, eu acho - eu geralmente escolho esses nomes arbitrariamente) .
z 0=?- Test testa a profundidade da pilha w / ze, se a pilha estiver vazia (leia-se: contém 0 objetos) , chama a ?macro.
? z0!=T q- A ?macro é nomeada para o ? dccomando embutido que lê uma linha de entrada do stdin, mas também adicionei outro zteste de profundidade da pilha, para que ele possa qutilizar todo o pequeno programa se puxar uma linha em branco ou atingir o EOF. Mas se não !preencher e preencher com êxito a pilha, ela chamará Test novamente.
d lm<M- Test então dduplicará a parte superior da pilha e comparará com $max (conforme armazenado em m) . Se mfor o menor valor, dcchama a Mmacro.
s0 lm- Mapenas abre a parte superior da pilha e a despeja no escalar fictício 0- apenas uma maneira barata de estourar a pilha. Também se lrecupera mantes de retornar ao Test.
p- Isso significa que, se mfor menor que o topo da pilha atual, a msubstitui (a dcópia da mesma, de qualquer maneira) e fica aqui pdefinida, caso contrário, não existe e o que quer que a entrada tenha sido pdefinida.
s0- Depois (porque pnão abre a pilha) , despejamos o topo da pilha 0novamente e depois ...
lTx- recursivamente load Test mais uma vez, em seguida, e xecute-lo novamente.
Assim, você pode executar esse pequeno trecho e digitar números de forma interativa no seu terminal e dcimprimir de volta o número digitado ou o valor $maxse o número digitado for maior. Também aceitaria qualquer arquivo (como um pipe) como entrada padrão. Ele continuará o loop de leitura / comparação / impressão até encontrar uma linha em branco ou EOF.
Algumas observações sobre isso - eu escrevi isso apenas para emular o comportamento da função shell, portanto, ele apenas lida com um número por linha. dcNo entanto, você pode lidar com tantos números separados por espaço por linha quanto gostaria de jogar nela. No entanto , devido à sua pilha, o último número de uma linha acaba sendo o primeiro em que opera, e, como está escrito, dcimprimiria sua saída ao contrário se você imprimisse / digitasse mais de um número por linha nela. lidar com isso é armazenar uma linha em uma matriz e depois trabalhá-la.
Como isso:
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"
Mas ... não sei se quero explicar isso com tanta profundidade. Basta dizer que, ao dcler cada valor da pilha, ele armazena seu valor ou $maxseu valor em uma matriz indexada e, uma vez que detecta a pilha novamente vazia, ele imprime cada objeto indexado antes de tentar ler outro linha de entrada.
E assim, enquanto o primeiro script faz ...
10 15 20 25 30 ##my input line
20
20
20
15
10 ##see what I mean?
O segundo faz:
10 15 20 25 30 ##my input line
10 ##that's better
15
20
20 ##$max is 20 for both examples
20
Você pode manipular carros alegóricos de precisão arbitrária se primeiro configurá-lo com o kcomando E você pode alterar os radios nput iou output independentemente - o que às vezes pode ser útil por razões que você não pode esperar. Por exemplo:
echo 100000o 10p|dc
00010
... que define o primeiro dcraio de saída para 100000 e depois imprime 10.