次のdc
ような2つの数値を比較できます。
dc -e "[$1]sM $2d $1<Mp"
... "$1"
は、最大値で"$2"
あり、それがより小さい場合に印刷する数値です"$1"
。また、GNU dc
が必要です-ただし、次のように同じことを移植可能にできます。
dc <<MAX
[$1]sM $2d $1<Mp
MAX
上記の例の両方では、0以外の何かに精度を設定することができます(デフォルト)のような${desired_precision}k
。どちらの場合も、演算子を使用して呼び出しを行うことができるため、両方の値が確実に数値であるdc
ことを確認する必要があります。system()
!
次の小さなスクリプト(および次のスクリプト)を使用して、入力も検証する必要があります- grep -v \!|dc
任意の入力をロバストに処理するものなど。また、dc
負の数値は_
接頭辞ではなく接頭辞で解釈されることも知っておく必要-
があります。これは、後者が減算演算子であるためです。
それとは別に、このスクリプトを使用すると、dc
連続した\n
ewlineで区切られた数字を必要なだけ読み取って$max
、woのどちらが小さいかに応じて値または入力のいずれかを出力します。
dc -e "${max}sm
[ z 0=? d lm<M p s0 lTx ]ST
[ ? z 0!=T q ]S?
[ s0 lm ]SM lTx"
だから... ...これらの各[
正方形の括弧付き]
広がりがありdc
、文字列されたオブジェクトS
のいずれか-そのそれぞれの配列にそれぞれをaved T
、?
またはM
。文字列を使用dc
して他のいくつかのことを行う可能性があるほかに、マクロとして実行することもできます。適切に配置すれば、完全に機能する小さなスクリプトが簡単に組み立てられます。x
dc
dc
スタックで動作します。すべての入力オブジェクトは最後にスタックされます。新しい入力オブジェクトが追加されるたびに、最後の最上位オブジェクトとその下のすべてのオブジェクトが1つずつスタックにプッシュされます。オブジェクトへのほとんどの参照は一番上のスタック値に対するものであり、ほとんどの参照はそのスタックの一番上をポップします(これにより、その下のすべてのオブジェクトが1つずつプルされます)。
メインスタックの他に、(少なくとも) 256個の配列もあり、各配列要素には独自のスタックが付属しています。ここではあまり使いません。必要にl
応じて文字列を保存し、必要に応じて文字列を実行できるように、文字列を保存するだけです。配列の上部の値x
をs
引き裂き$max
ましたm
。
とにかく、この少しdc
は、主に、シェルスクリプトが行うことを行います。GNU-ism -e
オプションを使用します- dc
通常は標準入力からパラメータを取得しますが、次のようにすることもできます。
echo "$script" | cat - /dev/tty | dc
... $script
上記のビットのように見えた場合。
次のように動作します:
lTx
-このl
OADSおよび電子x
ecutesの上に保存されたマクロT
(テストのために、私は推測-私は通常、それらの名前を任意に選択)。
z 0=?
- T
EST次いでWスタックの深さをテスト/ z
スタックが空の場合、及び(0オブジェクトを保持する読み取り)が呼び出し?
マクロ。
? z0!=T q
- ?
マクロは?
dc
、stdinからの入力行を読み取る組み込みコマンドに名前が付けられていますが、別のz
スタック深度テストも追加しました。これによりq
、空白行を取り込むかEOFにヒットした場合に、小さなプログラム全体を実行できます。ただし!
、スタックにデータが読み込まれずに正常に読み込まれた場合、T
estを再度呼び出します。
d lm<M
- T
ESTはその後うd
スタックの上部をuplicateとそれを比較する$max
(に格納されているようにm
)。m
が小さい値の場合dc
、M
マクロを呼び出します。
s0 lm
- M
スタックの一番上をポップしてダミーのスカラーにダンプします0
-スタックをポップするだけの安価な方法です。また、est に戻る前に再びl
鳴きます。m
T
p
-これはm
、スタックの現在のトップよりも小さい場合、それをm
置き換え(d
とにかくそれの複製)、ここでp
リントされることを意味します。そうでない場合、そうではなく、入力がp
代わりにリントされます。
s0
-その後(p
スタックがポップしないため)、スタックの先頭を0
再びダンプし、...
lTx
- もう一度再帰的にl
実行してから、再度実行します。T
x
そのため、この小さなスニペットを実行し、端末で対話形式で数字を入力し、入力した数字dc
または$max
入力した数字が大きかった場合の値を出力します。また、標準入力として任意のファイル(パイプなど)を受け入れます。空白行またはEOFが見つかるまで、読み取り/比較/印刷ループを継続します。
ただし、これに関するいくつかのメモ-シェル関数の動作をエミュレートするためだけにこれを書いたので、行ごとに1つの数値のみを堅牢に処理します。dc
ただし、行ごとにスペースで区切られた数だけ処理できます。ただし、スタックのため、行の最後の数字が最初に操作されるため、書かれているように、dc
行ごとに複数の数字を印刷/入力すると、出力が逆に印刷されます。それを処理するには、行を配列に格納し、それを機能させることです。
このような:
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"
しかし... ...私はそれを非常に深く説明したいかどうかわかりません。dc
スタックの各値を読み込むと、その値または$max
の値のいずれかをインデックス付き配列に保存し、スタックがもう一度空になると、別の読み込みを試みる前に各インデックス付きオブジェクトを出力すると言うだけで十分です。入力行。
そして、最初のスクリプトはそうですが...
10 15 20 25 30 ##my input line
20
20
20
15
10 ##see what I mean?
2番目は:
10 15 20 25 30 ##my input line
10 ##that's better
15
20
20 ##$max is 20 for both examples
20
k
コマンドで最初に設定した場合、任意の精度のフロートを処理できます。また、i
nputまたはo
utputの基数を個別に変更できます。これは、予期しない理由で役立つ場合があります。例えば:
echo 100000o 10p|dc
00010
...最初にdc
の出力基数を100000に設定してから、10を出力します。