Bash dc(1)和前导零

Bash dc(1)和前导零,bash,sh,dc,Bash,Sh,Dc,我有一个shell脚本,我用dc(1)进行了一些计算 我需要用前导零打印一个数字;我找不到一种简单直接的方法来处理dc本身,但手册中确实提到: Z 从堆栈中弹出一个值,计算位数 它有(或字符数,如果有) 是一个字符串)并推动它 号码。a的位数计数 数字不包括任何前导字符 零,即使在 基点的右边 这意味着有一种简单而直接的方法 我知道有无数种方法可以实现这一点,我相信脚本正在与其中一种方法愉快地运行。我只是好奇;-) 这里有一个例子,虽然不雅。这将打印出带有2个前导零的999。您需要复制更多数字的

我有一个shell脚本,我用dc(1)进行了一些计算

我需要用前导零打印一个数字;我找不到一种简单直接的方法来处理dc本身,但手册中确实提到:

Z
从堆栈中弹出一个值,计算位数 它有(或字符数,如果有) 是一个字符串)并推动它 号码。a的位数计数 数字不包括任何前导字符 零,即使在 基点的右边

这意味着有一种简单而直接的方法


我知道有无数种方法可以实现这一点,我相信脚本正在与其中一种方法愉快地运行。我只是好奇;-)

这里有一个例子,虽然不雅。这将打印出带有2个前导零的999。您需要复制更多数字的代码

#Push number to print on stack
999

# macro to print a zero
[[0]P]sa

# Print a zero if less than 5 digits
dZ5>a

# Print a zero if less than 4 digits
dZ4>a

# Print a zero if less than 3 digits
dZ3>a

# Print a zero if less than 2 digits
dZ2>a

# Print out number
p
尝试一下:

输入:

[lc1+dsc0nld>b]sb
[sddZdscld>bp]sa
999
12lax
3lax
输出:

000000999
999
输入:

[lc1+dsc0nld>b]sb
[sddZdscld>bp]sa
999
12lax
3lax
输出:

000000999
999
宏结束后,原始编号保留在堆栈上。使用的寄存器:
a
(宏)、
b
(宏)、
c
(计数)、
d
(数字)

说明:

a
执行设置,调用
b
并打印原始号码

  • sd
    -将要输出的位数存储在寄存器
    d
  • dZ
    -复制原始数字并按下其数字计数
  • dsc
    -复制该计数并将其存储在寄存器
    c
  • ld>b
    -从寄存器
    d
    加载所需数字,如果大于计数,则调用宏
    b
  • p
    -打印原始号码
b
输出零,直到计数大于所需位数

  • lc1+
    -从寄存器
    c
    加载计数并递增
  • dsc
    -复制计数并将其存储回寄存器
    c
  • 0n
    -输出不带换行符的零
  • ld>b
    -从寄存器
    d
    加载所需的数字,如果它仍然大于递增的计数,则再次循环运行宏
    b
    ,否则它将返回调用者(宏
    a
要使用任意前导字符,请执行以下操作:

[lclkZ+dsclknld>b]sb
[sksddZdscld>bp]sa
999 14 [ ] lax
           999
[abc] 12 [-] lax
---------abc
除其他寄存器外,它还使用
k
存储字符(实际上可能不止一个):


如果所需的长度数字大于原始字符串的长度,但小于两个字符串的长度(或整数倍),则填充字符串将被整体使用,因此结果可能比您要求的长度长。

给定的解决方案适用于十进制数。对于十六进制(以及任何其他输入)基数使用。e、 g

c=18A; dc <<< "16i${c^^}d0r[r1+r10/d0<G]dsGx4+r-[1-[0]nlGx]sY[d0<Y]dsGxr10op"
                ^ radix    formatted length ^       ^ leading symbol

我本来打算在
bc
中完成它,并将它所做的事情转储出去,但是GNU
bc
并没有作为
dc
的前端实现!顺便说一句,这可以通过一系列的堆栈交换来实现,而不需要使用那么多的寄存器,但是寄存器使它变得更容易。这是一个很好的答案——虽然比我想象的要复杂一些,但可能是最好的答案。谢谢:-)