Impedir que o grep seja encerrado em caso de incompatibilidade

19

Este script não ecoa "depois":

#!/bin/bash -e

echo "before"

echo "anything" | grep e # it would if I searched for 'y' instead

echo "after"
exit

Isso também aconteceria se eu removesse a opção -e na linha shebang, mas gostaria de mantê-la para que meu script pare se houver um erro. Eu não considero grep não encontrar correspondência como erro. Como posso evitar que isso seja tão abrupto?

    
por iago-lito 15.12.2016 / 17:23

5 respostas

20
echo "anything" | grep e || true

Explicação:

$ echo "anything" | grep e
### error
$ echo $?
1
$ echo "anything" | grep e || true
### no error
$ echo $?
0
### DopeGhoti's "no-op" version
### (Potentially avoids spawning a process, if 'true' is not a builtin):
$ echo "anything" | grep e || :
### no error
$ echo $?
0

O "||" significa "ou". Se a primeira parte do comando "falhar" (significando "grep e" retorna um código de saída diferente de zero), a parte após o "||" é executado, obtém sucesso e retorna zero como o código de saída ( true sempre retorna zero).

    
por 15.12.2016 / 17:36
4

Outra opção é adicionar outro comando ao pipeline - um que não falha:

echo "anything" | grep e | cat

Como cat agora é o último comando no pipeline, é o status de saída de cat , não de grep , que será usado para determinar se o pipeline falhou ou não.

    
por 10.11.2017 / 09:56
4

Uma maneira robusta de com segurança e opcionalmente grep messages:

echo something | grep e || [[ $? == 1 ]] ## print 'something', $? is 0
echo something | grep x || [[ $? == 1 ]] ## no output, $? is 0
echo something | grep --wrong-arg e || [[ $? == 1 ]] ## stderr output, $? is 1

De acordo com o manual posix , o código de saída 1 significa que não há linhas selecionadas e > 1 significa um erro.

    
por 02.03.2018 / 04:41
2

Outra opção:

...
set +e
echo "anything" | grep e
set -e
...
    
por 15.12.2016 / 20:09
2

Solução

#!/bin/bash -e

echo "before"

echo "anything" | grep e || : # it would if I searched for 'y' instead

echo "after"
exit

Explicação

set -e ou set -o errexit

Exit immediately if a pipeline (which may consist of a single simple command), a list, or a compound command (see SHELL GRAMMAR above), exits with a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test following the if or elif reserved words, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command's return value is being inverted with !. If a compound command other than a subshell returns a non-zero status because a command failed while -e was being ignored, the shell does not exit. A trap on ERR, if set, is executed before the shell exits. This option applies to the shell environment and each sub‐ shell environment separately (see COMMAND EXECUTION ENVIRONMENT above), and may cause subshells to exit before executing all the commands in the subshell.

Além disso, : é o comando sem efeito no Bash.

    
por 15.12.2016 / 18:05