2014-10-12 38 views
2

Iam新增了shell脚本。我有十进制数字,比如说[2, 1.2, 3.2, 3.2.2, 3.2.3]在bash中比较高达2点的十进制值

这里最高的数字是3.2.3,但是我的代码返回3.2。如何比较多达2个小数点的数字?

var=3.2.2 
var2=3.2.3 

这是正确的比较吗?

if (($(echo "$var2 > $var" | bc -l))); 

请帮

+0

[猛砸可能重复。如何比较两个字符串中的“版本”格式](http://stackoverflow.com/questions/4023830/bash-how-compare-two-strings-in-version-format) – user2325703 2014-10-13 19:54:06

回答

2

您需要拆分这些字符串 '' (IFS=.)并开始比较每个细分。

你可以找到this answer一个完整的例子,它允许您确定:

  • '3.0.4.10> 3.0.4.2'
  • '4.08 < 01年8月4日'
+0

在完整的版本排序脚本中很好找到。 – 2014-10-12 08:51:49

1

我不是在电脑上(只是iPad),但我会用IFS或参数替换将3个组件分开,然后通过将第一个组件乘以10,000,第二个组件乘以100并添加第三个组件,形成一个数字,然后您将拥有两个直接可比较的整数。

因此,一个函数应该是这样的:

#!/bin/bash 
function integerversion() 
{ 
    IFS=. read a b c <<< "$1" 
    [ -z $b ] && b=0 
    [ -z $c ] && c=0 
    echo $((a*10000+b*100+c)) 
} 

# Test it out 

[ $(integerversion "3") -gt $(integerversion "2.8") ] && echo "3 > 2.8" 
[ $(integerversion "2.2") -gt $(integerversion "1.9") ] && echo "2.2 > 1.9" 
[ $(integerversion "0.99") -lt $(integerversion "1.0") ] && echo "0.99 < 1.0" 

输出

3 > 2.8 
2.2 > 1.9 
0.99 < 1.0 
1

你所寻找的是一个版本排序,它存在于不同的可执行文件。另一个适合该法案的工具是sort。但是,由于您的值包含在变量中,而不包含在数字列表中,因此sort -t : -k 1.1n,2.2n,3.3n filename几乎没有用处,除非您想将值写入临时文件,并且它们将结果返回给数组(一个好主意)。即使如此,因为它可能,您可以根据您的v1v2实现短那种会服务宗旨:

#!/bin/bash 

[ -n "$1" ] && [ -n "$2" ] || { 
    printf "Error: insufficient input. Usage: %s ver_num1 ver_num2\n" "${0//*\//}" 
    exit 1 
} 

v1="$1"     # v1 
v2="$2"     # v2 
v1s=$v1     # saved copies of complete string 
v2s=$v2     # (same for v2) 

[ "$v1" = "$v2" ] && # test inputs are equal and exit 
echo "$v1 = $v2" && 
exit 0 

while :; do 
    tv1=${v1%%.*}  # tmpv1 stores the first number for v1 
    tr1=${v1#*.}  # trv1 stores the remaining digits for v1 
    tv2=${v2%%.*}  # (same for v2) 
    tr2=${v2#*.} 
    if [ "$tv1" = "" ] || [ "$tv2" = "" ]; then  # if different length and 
     [ -n "$tv1" ] && echo "$v1s > $v2s" && break # equal at this point 
     [ -n "$tv2" ] && echo "$v1s < $v1s" && break # longer string wins 
    fi 
    if [ "$tv1" -gt "$tv2" ]; then  # test 1st digit 
     echo "$v1s > $v2s" && break  # if > or <, output results and break 
    elif [ "$tv1" -lt "$tv2" ]; then 
     echo "$v1s < $v2s" && break 
    else        # if no determination, go to next digit 
     v1=$tr1   # set v1, v2 to remaining digits to loop again 
     v2=$tr2 
    fi 
done 

exit 0 

输出:

$ bash 3waySort.sh 3.2.2 3.2.3 
3.2.2 < 3.2.3 
$ bash 3waySort.sh 3.2.3 3.2.3 
3.2.3 = 3.2.3 
$ bash 3waySort.sh 3.2 3.2.3 
3.2 < 3.2.3 
$ bash 3waySort.sh 1.2.4.7 3.2.3 
3.2.3 > 1.2.4.7 

注:我添加一些额外的测试,并将值设置为arg1arg2以帮助您入门。

2
  • 纯巴什函数,你想要做什么和有错误checkings。
  • 返回码:0(成功)if if $1<$21 otherwise,and 2 if error occurred occurred。
  • 使用任意数量的点进行交易。
  • 点之间的数字可以有任意长度(但不应超过bash的最大整数:9223372036854775807,这似乎是版本主要/次要数字的右侧球场)。
  • 查看下面的示例,看看$1<$2是什么意思,当数字没有相同数量的点时。

在这里你去:

is_lt() { 
    # success if $1<$2 
    local x y sx sy i 
    IFS=. read -ra x <<< "$1" 
    IFS=. read -ra y <<< "$2" 
    (((sx=${#x[@]})==0 || (sy=${#y[@]})==0)) && return 2 
    for((i=0;i<sx && i<sy;++i)); do 
     [[ ${x[i]} =~ ^[[:digit:]]+$ && ${y[i]} =~ ^[[:digit:]]+$ ]] || return 2 
     ((10#${x[i]}<10#${y[i]})) && return 0 
     ((10#${x[i]}>10#${y[i]})) && return 1 
    done 
    return $((sx>=sy)) 
} 

一下:

$ is_lt 3.2.2 3.2.3; echo $? 
0 
$ is_lt 3.2.2 3.2.2; echo $? 
1 
$ is_lt 3.2.2 3.2.2.0; echo $? 
0 
$ is_lt 3.2.2 3.2.2.1; echo $? 
0 
$ is_lt 3.1 3.x; echo $? 
2 
$ # Error doesn't trigger if order could be determined early: 
$ is_lt 3.2.2 3.2.3.x; echo $? 
0 
$ is_lt 3.08.09 3.8.10; echo $? 
0 

你的情况:

var=3.2.2 
var2=3.2.3 
if is_lt "$var" "$var2"; then 
    echo "it works" 
else 
    echo "doesn't work" 
fi