0

This is a bash routine to compare two numbers with some defined intervals given by integers numbers:

#!/bin/bash

# The comparing function
function compareInterval {
 t1=$1
 t2=$2

 shift 2

 while (( "$2" )); do
     if ((  $t1 >= $1  &&  $t2 <= $2 )); then
         # got match
         return 0
     fi
 shift 2
 done

 return 1
}

# sample values
t_initial=2
t_final=4

# Invocation. Compares against 1-3, 3-5, 2-5
if compareInterval  $t_initial $t_final  1 3  3 5  2 5; then
    echo Got match
fi

If the intervals are given by real numbers, i.e., 1.234, how does the condition in the function change?

Py-ser
  • 1,860
  • 9
  • 32
  • 58

2 Answers2

1

Here's a new version of the code:

#!/bin/bash

function compareInterval {
 t1=$1
 t2=$2

 shift 2

while (( $(awk -v var="$2" 'BEGIN{ if (var=="") print 0; else print 1; }') )); do
     var1=$(awk -v t1="$t1" -v t2="$1" 'BEGIN{ print (t1 >= t2) }')
     var2=$(awk -v t3="$t2" -v t4="$2" 'BEGIN{ print (t3 <= t4) }')
     if [[  "$var1" -eq "1"  &&  "$var2" -eq "1" ]]; then
         # got match
         return 0
     fi
 shift 2
 done

 return 1
}


t_initial=4399.75148230007220954256
t_final=4399.75172111932808454256
if compareInterval $t_initial $t_final 4399.48390124308 4400.47652912846 3 5 2 5; then
    echo Got match
fi
condorwasabi
  • 616
  • 6
  • 19
  • Thanks. Are you sure that the line `while (( "$2" )); do` is properly read? – Py-ser Jul 10 '14 at 08:33
  • @condrwasabi, I mean, with a float, is that line read without error? – Py-ser Jul 10 '14 at 09:03
  • I tested the code and it seems to do what you asked for. There's no error because even if `$2` is a float, testing it in the while test condition doesn't lead to any errors. The numeric comparison with the intervals range is implemented in awk (in bash you couldn't do that easily). – condorwasabi Jul 10 '14 at 09:09
  • Just test it and see if it works for you. I'm telling you that it works for me even when I set real numbers. – condorwasabi Jul 10 '14 at 09:16
  • I have raised the question just because I receive an error indeed :) Perhaps it is due to other lines in the script, but I receive `./script: line 28: ((: 4400.47652912846 : syntax error: invalid arithmetic operator (error token is ".47652912846 ")`. The `line 28` is the line where the `while` cycle starts and the float is `$2` in the logic. – Py-ser Jul 10 '14 at 09:19
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57080/discussion-between-condorwasabi-and-py-ser). – condorwasabi Jul 10 '14 at 09:25
  • New updated version. Now it should work even with real numbers in the intervals. – condorwasabi Jul 10 '14 at 12:34
0

Just another pure bash solution:

#!/bin/bash

function compareInterval {
    t1=$1 t2=$2
    shift 2

    while [[ $# -ge 2 ]]; do
        is_ge "$t1" "$1" && is_le "$t2" "$2" && return 0  ## Got match.
        shift 2
    done
    return 1
}

function is_ge {
    local A1 A2 B1 B2

    if [[ $1 == *.* ]]; then
        A1=${1%%.*}
        A2=${1##*.}
    else
        A1=$1
        A2=0
    fi

    if [[ $2 == *.* ]]; then
        B1=${2%%.*}
        B2=${2##*.}
    else
        B1=$2
        B2=0
    fi

    (( L = ${#A2} > ${#B2} ? ${#A2} : ${#B2} ))

    A2=$A2'00000000000000000000'; A2=1${A2:0:L}
    B2=$B2'00000000000000000000'; B2=1${B2:0:L}

    (( A1 == B1 ? A2 >= B2 : A1 > B1 ))
}

function is_le {
    local A1 A2 B1 B2

    if [[ $1 == *.* ]]; then
        A1=${1%%.*}
        A2=${1##*.}
    else
        A1=$1
        A2=0
    fi

    if [[ $2 == *.* ]]; then
        B1=${2%%.*}
        B2=${2##*.}
    else
        B1=$2
        B2=0
    fi

    (( L = ${#A2} > ${#B2} ? ${#A2} : ${#B2} ))

    A2=$A2'00000000000000000000'; A2=1${A2:0:L}
    B2=$B2'00000000000000000000'; B2=1${B2:0:L}

    (( A1 == B1 ? A2 <= B2 : A1 < B1 ))
}

t_initial=2.4
t_final=4.5

if compareInterval "$t_initial" "$t_final" 1 3 3 5 2 5; then
    echo 'Got match.'
fi

Note: Of course sanity checks can be added but I find that not too necessary for now.

konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • That's why we have bc or awk :) – condorwasabi Jul 10 '14 at 09:00
  • @condorwasabi `bc` is an obvious reply. However I think the OP needs something that needs to be done in Bash. Forking for minor tasks also is a terrible solution commonly used by common scripters. And if you use `awk` for such purposes it's obviously a very ugly hack. – konsolebox Jul 10 '14 at 09:05
  • I appreciate your solution but the OP wanted a script that worked even when the interval numbers were real numbers. For example I executed your script and it crashes if t_initial or t_final are real numbers. It seems that the OP asked this question to solve this kind of potential errors. – condorwasabi Jul 10 '14 at 09:15
  • @condorwasabi Yes looks like I had some mistakes on it. It's now fixed. By the way this `sanity check` I was referring to was about anything that could also give syntax errors to `bc` if given. – konsolebox Jul 10 '14 at 09:22