1

I have a requirement for comparing the values with 4 decimal points. I tried with bc, but it didn't work. How can I do this?

amt="12.2.0.13" opn_amt="12.2.0.14"
if [ $(bc <<< "$amt <= $opn_amt") -eq 1 ]; then
  echo "12.2.0.13"
else
  echo "12.2.0.14" 
fi
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
  • 1
    Are these version numbers? They're a bit odd for decimal values, having multiple decimal points. – Benjamin W. Mar 22 '19 at 03:21
  • what if values are `12.2.0.13` and `12.12,0.13` ? In that case you should consider padding each `.` for 2 digits. So `12.2.0.13` should be `12.02.00.13`. Then it would be easy to compare. In case you version exceeds 2 digits, then consider padding for 3 or 4 digits. – Utsav Mar 22 '19 at 03:22
  • Yes these are version numbers, padding won't allow.. i am getting these values from logs and comparing both so we cannot pad.. – vasu madhineni Mar 22 '19 at 03:59
  • Possible duplicate of [How to compare two strings in dot separated version format in Bash?](https://stackoverflow.com/questions/4023830/how-to-compare-two-strings-in-dot-separated-version-format-in-bash) - has answers for both pure Bash implementations as well as using GNU `sort`. – Benjamin W. Mar 22 '19 at 04:10

3 Answers3

1

Please try below code;

To output larger IP:

amt="12.2.0.13";opn_amt="12.1.0.14";C=$opn_amt; for v in 1 2 3 4; do A=$(echo $amt | cut -d '.' -f$v); B=$(echo $opn_amt | cut -d '.' -f$v); if [ $A -gt $B ]; then C=$amt; break; fi; done; echo $C

To output less IP:

amt="12.1.0.13";opn_amt="12.1.0.14";C=$opn_amt; for v in 1 2 3 4; do A=$(echo $amt | cut -d '.' -f$v); B=$(echo $opn_amt | cut -d '.' -f$v); if [ $A -lt $B ]; then C=$amt; break; fi; done; echo $C

To do something based on conditon:

$ amt="12.2.0.14";opn_amt="12.1.0.14";C=0; for v in 1 2 3 4; do A=$(echo $amt | cut -d '.' -f$v); B=$(echo $opn_amt | cut -d '.' -f$v);if [ $A -lt $B ]; then C=1; break; fi; done
$ if [ $C -eq 0 ]
> then
> echo "amt is great or equal then opn_amt"
> else
> echo "amt is less than opn_amt"
> fi
amt is great or equal then opn_amt
ZMJ
  • 337
  • 2
  • 11
  • Hi tried this it is working but i need condition like if value equal or greater means one condition.. if the value less then i have to proceed to other condition – vasu madhineni Mar 22 '19 at 04:14
  • You can assign var C to 0 or 1 in different condition, and then use C as condition to do further operation. – ZMJ Mar 22 '19 at 04:19
0

If the number of digits between each . is fixed and same in both strings, you can compare by removing the . from the variables. So they will be considered integer before comparing.

sh-4.4$ amt="12.2.0.13"                                                                                                          
sh-4.4$ open_amt="12.2.0.14"                                                                                                     
sh-4.4$ [ "${amt//./}" -gt "${open_amt//./}" ] && echo "$amt" || echo "$open_amt"                                                
12.2.0.14  
sh-4.4$ 
Utsav
  • 7,914
  • 2
  • 17
  • 38
0

Here's a comparator implementation for ksh. Adapting it to other shells is left as an exercise for the reader.

function get_version_component {
    typeset -r version="$1"
    typeset -ri index="$2"
    typeset value=$(print -- "$version" | cut -d. -f$index -s)
    [[ "$value" == "" ]] && value=0
    [[ "$value" == +([0-9]) ]] || return 1
    print $value
    return 0
}

# Compare two version numbers, up to 20 levels deep.
# For comparison purposes, missing values are assumed to be zero (1.2.3.0 == 1.2.3).
# Output -1 on first < second, 0 if they are equal, 1 if first > second.
# (($(compare_versions 10.3.59.37 10.3.59) > 0)) && echo pass1
# Returns 0 on success, non-0 on invalid version number.
function compare_versions {
    [[ -z "$1" || -z "$2" ]] && return 1
    typeset -r first="${1}.0" second="${2}.0"
    typeset -i index=0 n1 n2
    for (( index = 1 ; index < 20 ; index++ ))
    do
        n1=$(get_version_component "$first" $index) || return 1
        n2=$(get_version_component "$second" $index) || return 1
        if ((n1 < n2))
        then
            print -- "-1"
            return 0
        elif ((n1 > n2))
        then
            print "1"
            return 0
        fi
    done
    print "0"
    return 0
}



# # Test cases
# # Equal
# compare_versions 10.3.59.37 10.3.59.37 || print errored
# compare_versions 10.3.59.0 10.3.59 || print errored
# compare_versions 10.3.59 10.3.59.0 || print errored
# 
# # Less
# compare_versions 9.2.59.37 10.3.59.37 || print errored
# compare_versions 10.2.59.37 10.3.59.37 || print errored
# compare_versions 10.3.59.37 10.3.59.39 || print errored
# compare_versions 10.3.59.37 10.3.60 || print errored
# compare_versions 10.3.59 10.3.59.37 || print errored
# 
# # Greater
# compare_versions 10.2.59.37 9.3.59.37 || print errored
# compare_versions 10.3.59.37 10.2.59.37 || print errored
# compare_versions 10.3.59.39 10.3.59.37 || print errored
# compare_versions 10.3.60 10.3.59.37 || print errored
# compare_versions 10.3.59.37 10.3.59 || print errored
# 
# # Errors
# compare_versions 10.x.59.37 10.3.59.37 && print "Error didn't 1"
# compare_versions 10.3.59.37 "" && print "Error didn't 2"
# compare_versions "" 9.3.59.37 && print "Error didn't 3"
# 
Perette
  • 821
  • 8
  • 17