我怎样才能让我的脚本为自己确定最大的数字?
我查看了我的环境变量,我发现这两个看起来很有希望:
~# declare -p BASH_VERSINFO HOSTTYPE
declare -ar BASH_VERSINFO=([0]="5" [1]="0" [2]="11" [3]="1" [4]="release" [5]="x86_64-slackware-linux-gnu")
declare -- HOSTTYPE="x86_64"
Run Code Online (Sandbox Code Playgroud)
...但我真的可以相信解析这些,以便得出关于 Bash 算术中最大数字是多少的结论吗?必须有更好的方法,以编程方式。有什么建议?
Pou*_*rko 19
Bash 算术使用有符号数。
所以快速的答案是:
((MAX=(1<<63)-1))
Run Code Online (Sandbox Code Playgroud)
但既然您希望脚本不知道它正在运行的系统的位数,那么让我们继续。
蛮力将是,在循环中不断加 1,直到达到溢出到负数的程度。但这可能需要数年时间!:-) 一种更快、更优雅的方法是使用简单的位移。
让我们找到符号位,即,让我们找到1最高有效位中的数字,以及所有其他位中的零,无论它们可能有多少。一旦我们有了那个数,我们就简单地减去1它,我们就会得到最大的有符号数。
((MAX=(1<<63)-1))
Run Code Online (Sandbox Code Playgroud)
或者,这是一个单线,没有循环。我们将一个数字的十六进制表示放在一个变量中,然后在将其传递给printf内置函数时通过变量扩展来屏蔽符号位:
printf -v MAX %x -1 && printf -v MAX %d 0x${MAX/f/7}
echo $MAX
Result:
9223372036854775807
Run Code Online (Sandbox Code Playgroud)
在与我的位不同的机器上,结果将是不同的数字。
只是为了说明,就我而言:
printf "MAX %X %d\nMIN %X %d\n" $MAX $MAX $MIN $MIN
MAX 7FFFFFFFFFFFFFFF 9223372036854775807
MIN 8000000000000000 -9223372036854775808
Run Code Online (Sandbox Code Playgroud)
关于 MIN 的一点说明:您可能希望限制自己使用((MIN=-MAX)),否则您偶尔会遇到一些算术运算的问题。
((MIN=-MAX)) ; printf "MIN %X %d\n" $MIN $MIN
MIN 8000000000000001 -9223372036854775807
Run Code Online (Sandbox Code Playgroud)
您可以在两步文本操作操作中获得最大数量。
TL; DR:在bash所有你需要做的是:
printf -v ff %x -1
printf -v max %d "0x${ff/#?/7}"
Run Code Online (Sandbox Code Playgroud)
而最小值可以通过以下附加操作获得:
# this uses the shell's own arithmetic engine
min="$((max+1))"
Run Code Online (Sandbox Code Playgroud)
要回答的OP的评论,注意bash器具printf的内置命令,默认情况下它有利于它的内置,因此它不会尝试调用外部printf命令,它通常可以作为一个独立的可执行文件下$PATH。
此外,上面使用bash的 自己的内置printf函数不会产生任何额外的进程。相反,它在 shell 的当前执行环境中运行,在其中创建变量$ff并$max按照方便的-v选项指定。
与上面相同,但在符合 POSIX 的语法中是:
ff="$(printf %x -1)"
max="$(printf %d "0x7${ff#?}")"
# to obtain the minimum number in shells that only
# support integer numbers you can just do like
# said for `bash`
min="$((max+1))"
# else for shells defaulting to floating-point numbers
# (such as ksh93) you might instead do one text-manipulation
# operation on top of the arithmetic addition
min="$(printf -- -%u "$((max+1))")"
# of course such result would only apply to the shell's
# integer capacities, not to its floating-point capacities
Run Code Online (Sandbox Code Playgroud)
请注意,使用上述符合 POSIX 的语法可能会为这些命令替换中的每一个生成一个(临时)进程,这取决于特定的 shell 是否优化了printf像那些简单的s。然而,即使 shell 确实为每个此类生成了一个进程printf,它通过简单地分叉自己来实现,因此它仍然依赖于自己的算术能力,而不是其他任意 shell 的算术能力。
这是假设 shell 实现printf为builtin,就像bash许多其他 shell 一样。未实现printf为内置的 shell 将使用(如果有)中printf可用$PATH的外部printf命令,就外部命令、操作系统的 C 库和 CPU 自身的能力而言,这将产生有效的结果,但可能不一定与shell 自己的匹配算术能力,例如mksh在 64 位机器上使用 32 位算术的情况。值得注意的是mksh可能不会printf作为内置命令实现,或者无论如何仍然更喜欢外部命令,并且如果它没有被这样编译,则ashfrombusybox可能不会printf作为内置命令实现。