dc(1)和前导零

时间:2011-03-17 08:17:23

标签: bash sh dc

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

我需要打印一个带前导零的数字;我无法通过dc本身找到一种简单直接的方法,但是该联机帮助确实提到了:

  

ž
  弹出堆栈中的值,计算位数   它有(或字符数,如果它   是一个字符串)并推动它   数。 a的数字计数   号码不包括任何领先   零,,即使那些出现在   小数点右边。

哪种意味着有一种简单明了的方式......

我知道有很多方法可以实现这一点,而且我的脚本与其中一个很愉快地运行。我只是好奇; - )

3 个答案:

答案 0 :(得分:3)

尝试一下:

输入:

[lc1+dsc0nld>b]sb
[sddZdscld>bp]sa
999
12lax

输出:

000000999

输入:

3lax

输出:

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来存储字符(实际上可能不止一个):

[XYZ] 6 [def] lax
defXYZ
8 [ab] lax
abababXYZ
4 [ghjikl] lax
ghijklXYZ

填充字符串是全部使用的,因此如果所需的长度数大于原始字符串的长度,但是小于两个字符串的长度(或整数倍),结果可能比您要求的长。< / p>

答案 1 :(得分:0)

这是一个例子,虽然不够优雅。这打印999与2前导零。您需要复制代码以获得更多数字。

#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

答案 2 :(得分:0)

给出的解决方案适用于十进制数字。对于十六进制(以及任何其他输入),使用基数。例如

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

您也可以尝试

   c=19;   dc <<< "10i${c^^}d0r[r1+r10/d0<G]dsGx4+r-[1-[_]nlGx]sY[d0<Y]dsGxr10op"
   c=607;  dc <<< " 8i${c^^}d0r[r1+r10/d0<G]dsGx8+r-[1-[*]nlGx]sY[d0<Y]dsGxr10op"
   c=1001; dc <<< " 2i${c^^}d0r[r1+r10/d0<G]dsGx8+r-[1-[ ]nlGx]sY[d0<Y]dsGxr10op"

GY是使用的寄存器。首先在堆栈上计算位数,然后计算要打印的符号数。

c=607;  dc <<< "8i${c^^}d0r[r1+r10/d0<G]dsGx f 8+r-[1-[*]nlGx]sY f [d0<Y]dsGxr10op"