运行./dice.sh 1 1 1 1时触发dc基数错误的原因排查
分析错误原因
让我们一步步拆解这个问题:
首先,错误提示dc input base must be a number between 2 and 16 inclusive说明dc在尝试设置输入基数时,使用了一个不在2-16范围内的数值。结合你的脚本和输入参数(1 1 1 1),问题出在以下两个关键环节:
1. tr命令未正确删除空格
脚本第一行的tr -d [:space:]存在写法错误:
dice=0$(echo $* | tr -d [:space:] | tr 1-6 0-5)
[:space:]是tr的字符类,用于匹配所有空白字符,但必须用单引号括起来。如果不加引号,shell会把它当作普通字符串(解析为字符:、s、p、a、c、e),而不是tr的字符类。这就导致:
- 输入参数中的空格(
1 1 1 1里的空格)根本没被删除 - 经过
tr 1-6 0-5替换后,得到的字符串是0 0 0 0(保留了空格) - 最终
dice变量的值是00 0 0 0(前面加了一个0,再加上带空格的替换结果)
2. dc命令的命令字符串未加引号
脚本中的dc调用没有把命令字符串用引号括起来:
eval "hex=$(dc -e 16o6i${dice}p)"
当dice包含空格时,shell会把dc -e 16o6i${dice}p拆分成多个参数,比如:
dc -e '16o6i0' '0' '0' '0p'
-e选项只接收第一个参数16o6i0作为命令执行,这部分是正常的(设置输出基数16,输入基数6,压入数字0)- 后面的
0、0、0p会被dc当作文件名,尝试读取这些文件的内容作为后续命令
如果你的当前目录恰好存在一个名为0的文件,且文件内容包含类似i0或i1的命令(比如误写入的内容),dc执行到i命令时,会把栈顶的0或1作为输入基数,而这两个数值都不在2-16的合法范围内,就会触发你看到的错误。
修复方案
修改脚本的两处错误即可解决问题:
# 1. 给tr的字符类加单引号,确保删除空格 dice=0$(echo $* | tr -d '[:space:]' | tr 1-6 0-5) # 2. 给dc的命令字符串加双引号,避免被shell拆分 hex=$(dc -e "16o6i${dice}p")
这样修改后,dice变量会变成00000(无空格),dc会正确执行命令16o6i00000p,将6进制的00000转换为16进制输出,不会再触发输入基数错误。
内容的提问来源于stack exchange,提问作者quantumpotato
相关产品推荐
相关产品推荐

