Comparando valores float no bash

1

Minha expressão if sempre é avaliada como TRUE de alguma forma. Variável ROTATION é 0.000 ou 90.000, um valor float ou parece ser

ROTATION="$(mediainfo --Inform="Video;%Rotation%" $VIDEO$ORIGINALEXTENTION)"
echo $ROTATION

ROTATION_PARAMETER=""

if [ $ROTATION -eq 90 ]
then
    ROTATION_PARAMETER=" --rotate=4"
fi

echo $ROTATION_PARAMETER

Como posso comparar uma variável com um valor?

    
por Vladimir Stazhilov 06.02.2015 / 16:40

5 respostas

3

Você pode usar o comando bc para este puspose:

echo "$ROTATION == 90"|bc

e você receberá 0 no caso de false e 1 no caso de true

P.S. Esteja ciente de que comparar para números de ponto flutuante de equivalência não é a coisa mais sábia em programação:)

    
por 06.02.2015 / 17:00
0

Você pode comparar valores como uma string:

{ printf "[ %.3f == %.3f ]\n" $ROTATION 90 | bash ; } && ROTATION_PARAMETER=" --rotate=4"

Ou até mesmo

[ $(printf "%.3f == %.3f" $ROTATION 90) ] && ROTATION_PARAMETER=" --rotate=4"

Esteja atento para que algumas localidades exijam , em vez . como separador decimal, portanto, $ROTATION deve estar em 90,000 form.

    
por 06.02.2015 / 17:17
0

Como você já está usando a sintaxe zsh em vez da sintaxe bash (não citando suas variáveis), basta alternar para zsh onde você pode fazer:

 if (( ROTATION == 90 )); then...

(isso também funcionaria em ksh93 ).

Mas se o valor for sempre expresso como 90.000 , você também poderá fazer uma comparação strong:

 if [ "$ROTATION" = 90.000 ]; then...
    
por 06.02.2015 / 17:55
0

Considere chamar uma linguagem de script que esteja um pouco mais preparada para lidar com valores de ponto flutuante, algo semelhante a:

ROTATION=...
if $( perl -e 'use POSIX "fmod";if(fmod($ENV{ROTATION}, 90.0)<0.001) {exit(0)} else{exit(1)}' )
then...

(pode ter esses códigos de retorno de saída para trás)

    
por 06.02.2015 / 17:34
0

Como são strings, você pode comparar várias strings concatenadas entre si. O balanceamento de valores é um meio simples de lidar com vários testes de shell de uma só vez.

[ "${num#90.}${num%[!0]*}" = "90${num%[!0]*}" ] && do_it

Mas isso só funciona se $num for definitivamente um número. Você pode validar um valor inteiro para $num como:

[ "$num" -eq "$num" ]

Ou um float como:

[ "${#num}${num#*.}" -ne "${num%.*}${#num}" ]

Mas case geralmente é melhor ...

case ".${num##*[!-.0-9]*}" in
(.|.[!9]*|.9[!0]*|.90.*[!0]*) 
! :;;esac 

No que diz respeito a utilitários externos, geralmente prefiro dc to bc porque ele pode ser usado para executar comandos arbitrários do sistema:

dc -e '[!echo execute arbitrary system command]s=' \
   -e '90 90.0 =='

Tudo dentro dos colchetes [] é uma string que é s aved para a matriz chamada = e que é executada como um comando dc se os dois principais valores na pilha principal (aqui 90 e 90.0) = um do outro. O primeiro operador ! dentro da cadeia é o operador ! , que executa como um comando do sistema tudo o que o segue. Você também pode ler a entrada para mais script dc para executar condicionalmente com o operador ? .

A sintaxe -e xpression é um GNUism, no entanto. Você pode obter o mesmo efeito portável com um heredoc ou ecoar os comandos em um cano para seu stdin.

Por exemplo:

! dc -e '[!kill -PIPE "$PPID"]s= 90 90.0 ==' && do_it
    
por 06.02.2015 / 17:23