bash -e sai quando let ou expr avalia para 0

Eu tenho um script bash que define -e para que o script saia em qualquer status de saída! = 0 .

Estou tentando fazer alguma aritmética de shell básica atribuída a variáveis e às vezes a expressão é igual a 0, o que faz com que o status de saída do comando let ou expr seja “1”.

Aqui está um exemplo:

#!/bin/bash -ex echo "Test 1" Z=`expr 1 - 1` || true echo "Z will print" let "A=4 - 4" echo "A WILL NEVER PRINT $A" Y=`expr 1 - 1` echo "Y WILL NEVER PRINT $Y" X=$(expr 2 - 2) echo "X WILL NEVER PRINT $X" 

O resultado é:

$ ./test_error.sh + echo "Test 1" Test 1 ++ expr 1 - 1 + Z=0 + true + echo "Z will print" Z will print + let "A=4 - 4" 

Meu a questão é qual é a maneira idiomática de script bash para permitir que o script falhe em erros reais de saída e não em aritmética básica igual a 0. Eu poderia sufocar todas essas expressões com:

A=`expr $C - $D` || true 

Mas isso parece hacky.

Resposta

Não use expr para aritmética. Está obsoleto há muito tempo: os shells agora têm aritmética incorporada, com a construção $((…)) (POSIX) ou com let incorporada (ksh / bash / zsh) ou a construção ((…)) (ksh / bash / zsh).

let e ((…)) retornar 1 (um código de status de falha) se a última expressão avaliada for 0. Para evitar que isso faça com que seu script saia em set -e, organize para a última expressão não deve retornar 0, por exemplo:

let "a = 2 - 2" 1 ((a = 2 - 2, 1)) 

Como alternativa, use o || true idioma:

((a = 2 - 2)) || true 

Como alternativa, faça sua aritmética dentro de $((…)) e suas tarefas fora. Uma atribuição retorna o status da última substituição de comando no valor, ou 0 se não houver substituição de comando, então você está seguro. Isso tem a vantagem de trabalhar em qualquer shell POSIX (como o traço).

a=$((2 - 2)) 

Resposta

Eu tinha o mesmo problema . tl; dr:

Se o último ARG [de let] for avaliado como 0, let retorna 1; let retorna 0 caso contrário .

Resposta

Use $(( $C - $D )) em vez de sua aritmática. É mais eficiente também.

Comentários

  • O que o torna mais eficiente do que dizer (( A = $C - $D ))?

Resposta

Esta sintaxe funciona para mim:

a=$((b + c)) 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *