bash não suporta nativamente uma comparação de intervalo, nem números de ponto flutuante, por isso temos que fazer alguns de nós mesmos. Eu também vou definir uma função e usar bc para o cálculo de ponto flutuante. Aqui está o resultado final e a suíte de testes:
# Call as 'compareRanges start end b1 f1 b2 f2 b3 f3...'
compareRanges() {
local t_initial=$1
local t_final=$2
shift 2
while [ ${#@} -gt 1 ]
do
local in_range=$(bc <<<"$t_initial >= $1 && $t_final <= $2")
if [ $in_range = 1 ]
then
# Debugging output to stderr - can be removed:
echo "[$t_initial,$t_final] is within [$1,$2]" >&2
return 0
fi
shift 2
done
# Debugging output to stderr - can be removed:
echo "[$t_initial,$t_final] is not within any ranges." >&2
return 1
}
# Basic integers from the example
compareRanges 1 3 2 4 && echo BAD || echo OK
compareRanges 1 3 1 3 && echo OK || echo BAD
compareRanges 1 3 0 4 && echo OK || echo BAD
# Fractional numbers
compareRanges 1.5 2.5 1.1 2.2 && echo BAD || echo OK
compareRanges 1.5 2.5 0.3 3.1 && echo OK || echo BAD
# Multiple ranges
compareRanges 5 7 1 4 2 6 3 9 && echo OK || echo BAD
compareRanges 5 7 1 2 3 4 5 6 7 8 && echo BAD || echo OK
A função compareRanges leva pelo menos dois argumentos. O primeiro é seu t_initial e o segundo é seu t_final . Pode levar arbitrariamente muitos outros argumentos em pares depois disso, que são seus begin1 , fin1 , begin2 , fin2 , em ordem.
O primeiro caso de teste compara os intervalos nos comentários sobre a questão: 1-3 e 2-4.
compareRanges 1 3 2 4 && echo BAD || echo OK
Portanto, 1 é t_initial , 3 é t_final , 2 é begin1 e 4 é fin1 .
Quando você quiser usar vários intervalos, liste-os em pares depois:
compareRanges 5 7 1 4 2 6 3 9 && echo OK || echo BAD
Aqui testamos contra 1-4, 2-6 e 3-9. No loop while , olhamos cada par e comparamos com t_initial e t_final .
Como bash não suporta números fracionários, usamos bc , uma calculadora de precisão arbitrária . Sua entrada é dada pela <<<"$t_initial >= $1" ... part: que alimenta a string na entrada padrão. $1 é o começo do intervalo que estamos vendo nesta iteração do loop, e $2 é o fim; Comparamos os limites inferior e superior ao mesmo tempo com && . bc produzirá 1 quando as comparações forem verdadeiras e 0 quando uma for falsa. Nós salvamos o resultado em in_range e a função é bem-sucedida ( return 0 ) quando os dois testes são verdadeiros.
Os números fracionários podem ser especificados apenas com a sua forma decimal comum:
compareRanges 1.5 2.5 0.3 3.1 && echo OK || echo BAD
bc lidará com números com quantos dígitos fracionários você quiser e com a magnitude que precisar.
No final, se nenhum dos pares limite corresponder, nós falhamos ( return 1 ). Você pode usar a função como:
if compareRanges $t_initial $t_final 2 4 11 19
then
...
fi
O conjunto de testes deve imprimir todos os "OK" quando você executá-lo.
Como alternativa, outros shells (como zsh ) do suportam valores de variáveis fracionárias. Se você pudesse executar seu script em um desses, você poderia evitar o uso de bc , embora a comparação ainda seja melhor em uma função. Pelo menos no caso de zsh eles são floats, então eles não são necessariamente precisos; bc estará sempre correto.