Answers:
您可以只比较两个数字,dc
例如:
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
您希望提供的按顺序的双行分隔的数字,并为您的$max
值或输入中的每一个打印输出,具体取决于哪一个值较小:
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
在堆栈上工作。所有输入对象都堆叠在最后一个对象上-每个新输入对象将添加的最后一个顶部对象及其下面的所有对象向下推一推。对对象的大多数引用都指向栈顶值,并且大多数引用将栈顶弹出(这会将其下的所有对象向上拉一位)。
除主堆栈外,还(至少)有 256个数组,每个数组元素都带有一个自己的堆栈。我在这里用的不多。我只是按上述方式存储了字符串,所以我可以l
在需要时对其进行x
遍历并有条件地执行它们,然后s
将$max
值撕裂到m
数组顶部。
无论如何,这一点都可以dc
完成您的shell脚本。它确实使用了GNU-ism -e
选项- dc
通常从standard-in中获取其参数-但您可以执行以下操作:
echo "$script" | cat - /dev/tty | dc
...如果$script
看起来像上面的位。
它的工作原理如下:
lTx
-此l
操作x
可将存储在顶部的宏删除T
(为了测试,我想-我通常会随意选择这些名称)。z 0=?
- T
EST然后测试堆栈深度瓦特/ 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
无论如何是它的uplicate)并在此处进行p
漂洗,否则不进行漂洗,而是清除任何输入p
。s0
-之后(因为p
不会弹出堆栈),我们0
再次将堆栈的顶部转储到其中,然后...lTx
-递归l
OAD T
EST一次则E x
再次ecute它。因此,您可以在终端上运行此小片段并以交互方式键入数字,然后dc
将输入的数字或$max
键入的数字较大时的值打印回给您。它还将接受任何文件(例如管道)作为标准输入。它将继续读取/比较/打印循环,直到遇到空白行或EOF。
不过,有些注意事项-我编写此代码只是为了模拟您的shell函数中的行为,因此它仅能可靠地处理每行一个数字。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?
第二个是:
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。
dc
每隔一段时间就传送一些数字,以使其保持脚尖。
[string]P91P93P[string]P
。因此,我sed
可能对您有帮助:sed 's/[][]/]P93]&[1P[/g;s/[]3][]][[][1[]//g'
这应该始终使用字符串右括号,然后是a P
,然后是正方形的十进制ascii值以及另一个来正确替换正方形P
。然后用[
方括号将字符串继续。Dunno如果您搞砸了w / dc
的字符串/数字转换功能,但是-特别是当w /组合使用时od
-可能会很有趣。
如果您知道要处理两个整数a
和b
,那么使用三元运算符进行的这些简单的shell算术展开足以给出数值最大值:
$(( a > b ? a : b ))
和数字最小值:
$(( a < b ? a : b ))
例如
$ a=10
$ b=20
$ max=$(( a > b ? a : b ))
$ min=$(( a < b ? a : b ))
$ echo $max
20
$ echo $min
10
$ a=30
$ max=$(( a > b ? a : b ))
$ min=$(( a < b ? a : b ))
$ echo $max
30
$ echo $min
20
$
这是一个shell脚本来演示:
#!/usr/bin/env bash
[ -z "$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }
read number
echo Min: $(( $number < $1 ? $number : $1 ))
echo Max: $(( $number > $1 ? $number : $1 ))
max=$(( a >= b ? a : b ))
,但结果完全相同-如果a和b相等,那么返回哪个返回值并不重要。那是你要的吗
if (( a >= b )); then echo a is greater than or equal to b; fi
这是您要的吗?(请注意使用(( ))
此处代替$(( ))
)
sort
并head
可以这样做:
numbers=(1 4 3 5 7 1 10 21 8)
printf "%d\n" "${numbers[@]}" | sort -rn | head -1 # => 21
O(n log(n))
max的有效实现O(n)
。但是,这几乎没有什么意义n=2
,因为产生两个进程的开销要大得多。
numbers="1 4 3 5 7 1 10 21 8";
echo $numbers | tr ' ' "\n" | sort -rn | head -n 1
max=0; for x in $numbers ; do test $x -gt $max && max=$x ; done
您可以为其定义预定义的数学函数库,bc
然后在命令行中使用它们。
例如,在文本文件中包括以下内容~/MyExtensions.bc
:
define max(a,b){
if(a>b)
{
return(a)
}else{
return(b)
}
}
现在您可以致电bc
:
> echo 'max(60,54)' | bc ~/MyExtensions.bc
60
仅供参考,在线有免费的数学库函数,例如该函数。
使用该文件,您可以轻松计算出更复杂的函数,例如GCD
:
> echo 'gcd (60,54)' | bc ~/extensions.bc -l
6
bc
函数调用之前将函数定义也传递到。那么就不需要第二个文件了:)
评论太久了:
尽管您可以使用sort | head
或sort | tail
组合来完成这些操作,但在资源和错误处理方面似乎都不是很理想。就执行而言,组合意味着产生2个进程只是为了检查两行。这似乎有些过大。
更严重的问题是,在大多数情况下,您需要知道输入是理智的,仅包含数字。@glennjackmann的解决方案巧妙地解决了这个问题,因为printf %d
应该禁止使用非整数。它也不适用于浮点数(除非您将格式说明符更改为%f
,否则会遇到舍入问题)。
test $1 -gt $2
会向您指示比较是否失败(退出状态2表示测试期间发生错误。由于这通常是内置的shell,因此不会产生其他进程-我们所说的是数百个命令执行速度提高了两倍,但仅适用于整数。
如果您碰巧需要比较几个浮点数,则有趣的选择可能是bc
:
define x(a, b) {
if (a > b) {
return (a);
}
return (b);
}
将等同于test $1 -gt $2
,并在shell中使用:
max () { printf '
define x(a, b) {
if (a > b) {
return (a);
}
return (b);
}
x(%s, %s)
' $1 $2 | bc -l
}
仍然比printf | sort | head
(两个数字)快2.5倍。
如果您可以依赖中的GNU扩展bc
,那么您还可以使用该read()
函数将数字直接读入bc
清单。
dc -e "${max}sm[z0=?dlm<Mps0lTx]ST[?z0!=Tq]S?[s0lm]SMlTx"
-哦,除了dc
整个事情(回声除外,尽管可以) -它会读取stdin并$max
根据其中的一个打印输出或输入数字较小。无论如何,我不太在乎解释它,而且您的答案比我要写的要好。所以请给我投票。
dc
好的脚本会非常好,这些天很少看到RPN。
dc
能够自己完成I / O,那将比它更加优雅。
要获得$ a和$ b的较大值,请使用以下命令:
[ "$a" -gt "$b" ] && $a || $b
但是您需要解决此问题,您可能不需要执行该数字,因此要使用“ echo”显示两者中的较大值
[ "$a" -gt "$b" ] && echo $a || echo $b
上面的代码非常适合shell函数,例如
max() {
[ "$1" -gt "$2" ] && echo $1 || echo $2
}
要将两者中较大的一个分配给变量,请使用以下修改版本:
[ "$a" -gt "$b" ] && biggest=$a || biggest=$b
或使用定义的功能:
biggest=$( max $a $b )
功能的变化还使您有机会巧妙地添加输入错误检查。
要返回两个小数/浮点数的最大值,可以使用 awk
decimalmax() {
echo $1 $2 | awk '{if ($1 > $2) {print $1} else {print $2}}';
}
编辑:使用此技术,您可以创建一个“限制”功能,该功能可以按照您的编辑/注释进行其他操作。此函数将返回两者中的较低者,例如:
limit() {
[ "$1" -gt "$2" ] && echo $2 || echo $1
}
我喜欢将实用程序函数放入一个单独的文件中,进行调用myprogram.funcs
并在脚本中使用它,如下所示:
#!/bin/bash
# Initialization. Read in the utility functions
. ./myprogram.funcs
# Do stuff here
#
[ -z "$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }
read number
echo $( limit $1 $number )
FWIW仍然可以完成您的操作,即使您的版本更详细,它的版本也同样有效。
更为紧凑的形式并不一定会更好,但是可以防止脚本混乱。如果您有许多简单的if-then-else-fi构造,脚本将迅速扩展。
如果要在单个脚本中多次重复使用大号或小号支票,请将其放入函数中。函数格式使调试和重用更加容易,并且允许您轻松替换脚本的该部分,例如,使用awk命令可以处理非整数十进制数字。
如果是单个用例,则只需内联代码即可。
通过shell脚本,可以使用任何 Java公共静态方法(例如Math.min())。在Linux上的bash中:
. jsbInit
jsbStart
A=2
B=3
C=$(jsb Math.min "$A" "$B")
echo "$C"
这需要Java Shell Bridge https://sourceforge.net/projects/jsbridge/
非常快,因为方法调用是内部管道传递的;无需任何过程。
大多数人只会做sort -n input | head -n1
(或尾巴),对于大多数脚本编写情况来说已经足够了。但是,如果您在一行而不是一列中有数字,这会有些笨拙-您必须以正确的格式(tr ' ' '\n'
或类似格式)将其打印出来。
Shell并非完全适合于数值处理,但是您可以轻松地将其传递到其他更好的程序中。根据您自己的喜好,您可以拨打max电话dc
(有点混乱,但是如果您知道自己在做什么,那很好-请参阅mikeserv的回答)或awk 'NR==1{max=$1} {if($1>max){max=$1}} END { print max }'
。或者可能,perl
或者python
您愿意。一种解决方案(如果您愿意安装和使用鲜为人知的软件)ised
(特别是如果您的数据位于一行中:您只需要这样做ised --l input.dat 'max$1'
)。
因为您要输入两个数字,所以这太过分了。这应该足够了:
python -c "print(max($j,$k))"
sys.argv
:python2 -c 'import sys; print (max(sys.argv))' "$@"
sort + head
但python
不能计算的参数不会计算。
python
之所以使用是因为它很简洁。
python
顽固(或者因为它不需要fork和额外的巨大解释器)。或两者兼而有之。