在bash中将十进制值与最多2个点进行比较

在bash中将十进制值与最多2个点进行比较,bash,decimal,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) )); 请帮助您需要将这些字符串按“.”(IFS=。)拆分,然后开始比较每个段 您可以在中找到完整的示例,该示例允许您确定: “3.0.4.10>3.0.4.2” “4.08 1

我不熟悉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) ));

请帮助

您需要将这些字符串按“.”(
IFS=。
)拆分,然后开始比较每个段

您可以在中找到完整的示例,该示例允许您确定:

  • “3.0.4.10>3.0.4.2”
  • “4.08<4.08.01”
我不在电脑前(只在iPad上),但我会用IFS或参数代换将3个分量分开,然后将第一个分量乘以10000,第二个分量乘以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"
#/bin/bash
函数integerversion()
{
IFS=.读a b c 2.8
2.2 > 1.9
0.99 < 1.0

您正在寻找的是一个版本的排序,它存在于各种可执行文件中。另一个适合这一要求的工具是
排序
。但是,由于您的值包含在变量中,而不是在数字列表中,
排序-t:-k 1.1n,2.2n,3.3n文件名
几乎没有用处,除非您想编写va将值输出到临时文件,并对其进行排序,以数组形式返回结果(一个好主意)。尽管如此,您可以根据
v1
v2
实现短排序,以达到以下目的:

#!/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
!/bin/bash
[-n“$1”]&&&[-n“$2”]||{
printf“错误:输入不足。用法:%s ver\u num1 ver\u num2\n”“${0/*\/}”
出口1
}
v1=“$1”#v1
v2=“$2”#v2
v1s=$v1#保存的完整字符串副本
v2s=$v2#(与v2相同)
[“$v1”=“$v2”]&&&#测试输入相等并退出
回显“$v1=$v2”&&
出口0
当:;做
tv1=${v1%%.*}#tmpv1存储v1的第一个数字
tr1=${v1}}#trv1存储v1的剩余数字
tv2=${v2%%.*}#(与v2相同)
tr2=${v2#*。}
如果[“$tv1=”]| |[“$tv2=”];那么#如果长度和
[-n“$tv1”]&&echo“$v1s>$v2s”&&break#在这一点上相等
[-n“$tv2”]&&echo“$v1s<$v1s”&&break#更长的字符串获胜
fi
如果[“$tv1”-gt“$tv2”];则#测试第一位数字
回显“$v1s>$v2s”&中断#if>或1.2.4.7
注意:我添加了一些额外的测试,并将要通过的值设置为
arg1
arg2
,让您开始。

  • 一个简短的纯Bash函数,可以执行您想要的操作,并进行错误检查

  • 返回代码:
    0
    (成功)如果
    $1在完整版本排序脚本中找到,则返回代码。可能重复
    
    #!/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
    
    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