在bash中比较小数值最多2个点

时间:2014-10-12 08:05:29

标签: bash decimal

我刚接触shell脚本。我有小数,请说[2, 1.2, 3.2, 3.2.2, 3.2.3]

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

var=3.2.2
var2=3.2.3

这是比较的正确方法吗?

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

请帮忙

4 个答案:

答案 0 :(得分:2)

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

您可以在this answer中找到完整的示例,以便您确定:

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

答案 1 :(得分:2)

  • 一个简短的纯Bash 函数,可以执行您想要的操作并进行错误检查。
  • 返回代码:0(成功)如果$1<$21则为{},2如果发生错误。
  • 处理任意数量的点。
  • 点之间的数字可以有任意长度(但不应该超过bash&#39; s最大整数: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

答案 2 :(得分: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

答案 3 :(得分:1)

您要查找的是版本排序,它存在于各种可执行文件中。适合该法案的另一个工具是sort。但是,由于您的值包含在变量中而不包含在数字列表中,因此sort -t : -k 1.1n,2.2n,3.3n filename除非您想将值写入临时文件并且sort它们将结果返回到数组(一个好主意)。尽管如此,您可以根据用于此目的的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以便开始使用。