se declaração baseada em um comando

2

Eu encontrei este caminho para fazer comandos if :

$if echo test | grep st ; then echo yes ; fi ; echo $?
test
yes
0

Parece bom. Vamos tentar um não-jogo:

$if echo test | grep 123 ; then echo yes ; fi ; echo $?
0

Isso não está certo. A instrução if funciona corretamente, mas retorna um código de saída zero.

Alguém pode explicar isso para mim?

    
por Lumify 27.10.2017 / 16:37

2 respostas

4

$? após um bloco if contém o status de saída da instrução if . O padrão especifica que

The exit status of the if command shall be the exit status of the then or else compound-list that was executed, or zero, if none was executed.

No primeiro caso, você está vendo o status de saída do comando echo yes . No segundo caso, nenhum comando é executado em um bloco then ou else , portanto, o status de saída é 0.

    
por 27.10.2017 / 16:43
1

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.

    
por 27.10.2017 / 16:44

Tags