Atribua o resultado do comando canalizado se ele for bem-sucedido

1

Eu quero atribuir minha variável a a primeira palavra do resultado do comando func <some_arg> somente se ela não falhar. E se falhar, preciso registrar isso.

O que eu fiz até agora é:

func() {
    if [[ $1 -eq 1 ]]
    then
        echo 'hello world'
        return 0
    fi

    echo 'Something wrong has happened!' >> path/to/dev.log
    return 2
}

a=$(func 1)
r=$?

if [[ $r -eq 0 ]]
then
    a=$(awk '{ print $1 }' <<<"$a")
fi

Isso funciona, é claro, mas eu não gosto de atribuir minha variável a duas vezes.

Eu tentei isso:

  a=$(func 2 | awk '{ print $1 }') || echo 'Something wrong has happened!' >> path/to/dev.log

Mas não registra nada

Existe uma maneira melhor?

    
por smarber 28.02.2018 / 10:36

3 respostas

2

Você pode usar set -o pipefail para obter o erro da parte anterior do pipeline:

The return status of a pipeline is the exit status of the last command, unless the pipefail option is enabled. If pipefail is enabled, the pipeline's return status is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands exit successfully.

$ foo() { [[ "$1" = 1 ]] || return 1; echo "hello world"; }
$ a=$(set -o pipefail; foo 2 | awk '{print $1}' || echo "fail..." >&2)
fail...

Mas, na verdade, não vejo por que atribuir duas vezes seria um problema. Em essência, você apenas modifica o valor que obteve se o comando for bem-sucedido ou o ignora se ele falhar.

Além disso, você pode condensar essa lógica um pouco:

if a=$(foo 1); then
   a=${a%% *};
   echo "first word of a is '$a'"; 
   # do some work with $a...
else
   echo "error..." >&2;
fi

imprime

first word of a is 'hello'
    
por 28.02.2018 / 11:01
0

O shell tem várias maneiras nativas de analisar a primeira palavra de uma string:

  1. Recorte pelo sufixo - ${a%% *}

  2. Atribuir a parâmetros posicionais - set -- ${a} - o resultado será em $1 . Você pode simplificar isso com set -- $(func 1) .

  3. Divida em elementos de matriz ( bash apenas) - a=( $(func 1) ) - o resultado será em ${a[0]} .

por 28.02.2018 / 10:55
0

Um problema com seu código é que ele atropela a , mesmo se a função func retornar um resultado diferente de zero.

Em vez disso:

#!/bin/sh

func () {
    if [ "$1" -eq 1 ]; then
        echo 'some sort of logging stuff' >>logfile
        return 1
    fi

    echo 'hello world'
}

a="a string"

if b=$( func 0 ); then
    a=${b%% *}
fi

printf '1: a = "%s"\n' "$a"

a="a string"

if b=$( func 1 ); then
    a=${b%% *}
fi

printf '2: a = "%s"\n' "$a"

A execução disso produzirá

1: a = "hello"
2: a = "a string"

Como você pode ver, no segundo caso, a mantém seu valor.

    
por 28.02.2018 / 11:10

Tags