Posso usar operadores de comparação no caso?

3

Estou construindo uma função que calculará a bitola do fio necessária, dada a amperagem, a distância (em pés) e a queda de tensão permitida.

Posso calcular os "mils circulares" dados esses valores e, com isso, obter o AWG exigência . Comecei a criar uma declaração if elif grande para comparar os mils circulares com o indicador respeitado, mas acredito que case é a ferramenta certa para isso.

Ainda não encontrei exemplos de casos usados para comparar números, por isso estou pensando se é possível fazer algo como abaixo:

what.gauge () {

    let cmils=11*2*$1*$2/$3
    let amils=17*2*$1*$2/$3


    case $cmils in

        320-403)
            cawg="25 AWG"
            ;;
        404-509)
            cawg="24 AWG"
            ;;
        510-641)
            cawg="23 AWG"
            ;;

        etc...

}
    
por Jesse_b 08.08.2017 / 04:02

4 respostas

4
case $cmils in

    3[2-9][0-9]|40[0-3])
        cawg="25 AWG"
        ;;
    40[4-9]|4[1-9][0-9]|50[0-9])
        cawg="24 AWG"
        ;;
    51[0-9]|6[0-3][0-9]|64[01])
        cawg="23 AWG"
        ;;
    
por 08.08.2017 / 04:20
9

Shell POSIX

Como você está procurando testes aritméticos e o caso não faz aritmética, if-then parece a abordagem natural:

if [ "$cmils" -lt 320 ]
then
        cawg="??"
elif [ "$cmils" -le 403 ]
then
        cawg="25 AWG"
elif [ "$cmils" -le 509 ]
then
        cawg="24 AWG"
elif [ "$cmils" -le 641 ]
then
        cawg="23 AWG"
fi

Apenas Bash

Eu prefiro soluções portáteis, mas algumas pessoas são apaixonadas pela sintaxe aritmética do bash:

if ((cmils < 320))
then
        cawg="??"
elif ((cmils <= 403))
then
        cawg="25 AWG"
elif ((cmils <= 509))
then
        cawg="24 AWG"
elif ((cmils <= 641))
then
        cawg="23 AWG"
fi

Isso é mais poderoso e mais frágil do que a sintaxe POSIX. Para ver o porquê, experimente este código depois de definir cmils=cmils .

    
por 08.08.2017 / 04:23
5

Como outros já disseram, case não suporta operadores de comparação, apenas glob matching de padrões.

No entanto, você pode fazer um conjunto de if / elif / fi declarações parecer mais como uma declaração de caso formatando-a de forma diferente. por exemplo, com base na resposta de John1024:

if   [ "$cmils" -lt 320 ]; then cawg='??'
elif [ "$cmils" -le 403 ]; then cawg='25 AWG'
elif [ "$cmils" -le 509 ]; then cawg='24 AWG'
elif [ "$cmils" -le 641 ]; then cawg='23 AWG'
fi

ou até mesmo:

[ "$cmils" -ge 320 ] && [ "$cmills" -le 403 ] && cawg='25 AWG'
[ "$cmils" -ge 404 ] && [ "$cmills" -le 509 ] && cawg='24 AWG'
[ "$cmils" -ge 510 ] && [ "$cmills" -le 641 ] && cawg='23 AWG'

NOTA: ao contrário de qualquer coisa usando elif , essa variante tem a desvantagem de executar pelo menos o primeiro teste de cada uma dessas linhas. Usar elif irá ignorar todos os testes restantes depois que qualquer teste for avaliado como verdadeiro. Você poderia colocar algo assim em uma função e adicionar && return após configurar cawg .

Pessoalmente, acho que qualquer uma delas é muito mais legível (sem todos os feedfeeds extras e recuo alternado que bagunça as coisas), mas as opiniões variam muito sobre essa questão específica de estilo de codificação / indentação:)

Com tudo alinhado nas mesmas colunas (ou muito próximas), elas são mais fáceis de copiar, colar e editar. O que é bom quando se usa o único editor verdadeiro.

    
por 08.08.2017 / 04:48
1

Você pode mapear um valor em um intervalo e, em seguida, use o número de índice desse intervalo em uma instrução case :

cmil_limits=(320 404 510 642)
index=0
for limit in "${cmil_limits[@]}"
do
        if [ "$cmils" -lt "$limit" ]
        then
                break
        fi
        ((index++))
done
case "$index" in
   0)                   # < 320
        cawg="??"
        ;;
   1)                   # 320-403
        cawg="25 AWG"
        ;;
   2)                   # 404-509
        cawg="24 AWG"
        ;;
   3)                   # 510-641
        cawg="23 AWG"
        ;;
   4)                   # > 641
        cawg="??"
        ;;
esac

Se $cmils for menor que 320, nós saímos do loop for em sua primeira iteração, com index=0 . Se $cmils for & nlt; 320 (isto é, ≥ 320), nós incrementamos index (→ 1 ) e passamos para a próxima iteração. Então, se $cmils for < 404 (ou seja, ≤ 403, assumindo que é um número inteiro), nós saímos do loop com index=1 . E assim por diante. Se $cmils for & nlt; 642, �de 642 e, consequentemente, > 641, então corremos para o final do loop for e obtemos index=4 .

Isso tem as vantagens de manter os valores de corte juntos tudo na mesma linha, e você não precisa manter números redundantes (por exemplo, seu código atual e o de outra resposta, listas ambos 403 e 404, e ambos 509 e 510 - que é redundante, e mais trabalho para manter, se os números mudarem. Eu não sei se isso é uma preocupação do mundo real.)

cmil_limits é uma matriz. O bash, o ksh e alguns outros shells suportam matrizes, mas outros não. Se você precisa fazer algo assim em um shell que não suporta matrizes, você pode simplesmente colocar a lista diretamente na instrução for :

for limit in 320 404 510 642
do
    ︙

ou use a lista de parâmetros do shell como uma matriz:

set -- 320 404 510 642
for limit in "$@"
do
    ︙

Algumas conchas permitem que você abrevie as informações acima:

set -- 320 404 510 642
for limit
do
    ︙

((…)) aritmética é também um bashismo (como é a instrução let ). Se você precisa fazer algo assim em um shell que não suporta ((…)) aritmética, você pode substituir o

        ((index++))
Instrução

(para incrementar index ) com

        index=$(expr "$index" + 1)

Observe que os espaços antes e depois do + são obrigatórios.

    
por 08.08.2017 / 09:25

Tags