Do manual do bash (formatação e ênfase adicionada):
if list; then list; [ elif list; then list; ] ... [ else list; ] fi
The if list is executed. If its exit status is zero, the then list is executed. Otherwise, each elif list is executed in turn, and if its exit sta‐
tus is zero, the corresponding then list is executed and the command completes. Otherwise, the else list is executed, if present. The exit status
is the exit status of the last command executed, or zero if no condition tested true.
Então, a parte importante é estar ciente do status de saída do o que você está realmente vendo. No seu exemplo, echo test | grep 123
o último comando não saiu com sucesso. Se você fez grep
primeiro e depois testou o status de saída, verá que ele retorna um status de saída diferente de zero:
$ grep 'noexist' /etc/passwd
$ echo $?
1
Por outro lado, dentro da instrução if o comando como condição não testou true, portanto, de acordo com as especificações e o status de saída manual é 0.
Em nota lateral, por favor, faça grep '123'
, porque o padrão sem aspas pode ser todo outro saco de problemas se houver um arquivo 123 em seu diretório atual.
Nota lateral sobre padrões de grep e citações
Stephen Kitt solicitou nos comentários elaboração do último parágrafo. Isso não está necessariamente relacionado ao tópico desta questão e isso foi abordado aqui , e eu respondi algo semelhante aqui , mas eu vou na tangente porque isso é divertido. Vamos ver dois exemplos.
Aqui, temos grep input
, string simples sem aspas. A sintaxe de grep
é tal que irá considerar a primeira string como padrão. Não tem problema aqui, isso funciona:
bash-4.3$ strace -e trace=execve grep input <<< "this is input line"
execve("/bin/grep", ["grep", "input"], [/* 80 vars */]) = 0
this is input line
+++ exited with 0 +++
No entanto, veja o que acontece quando você tem (o que você acha que é) expressão regular.
bash-4.3$ strace -e trace=execve grep input* <<< "this is input line"
execve("/bin/grep", ["grep", "input.txt", "input.txt.bak"], [/* 80 vars */]) = 0
+++ exited with 1 +++
O shell viu seu *
e executou a expansão do nome do caminho. E agora o comando real real que o shell executa é grep some_file_1 some_file_2 some_file_3
e, de acordo com a sintaxe grep
- grep [OPTIONS] PATTERN [FILE...]
, o comando agora procurará a string input.txt
dentro de input.txt.bak
. De fato, olhe para isto:
bash-4.3$ echo "I have input.txt here" > input.txt.bak
bash-4.3$ grep input* <<< "this is input line"
I have input.txt here
A string de entrada é completamente ignorada, grep
procura apenas os nomes de arquivos expandidos e você tem resultados que não pretendia ter.