Os programas `if` e` then` são realmente

15

Eu li que ponto e vírgula é usado para separar programas:

$ echo 3; ls -la

Isso significa que if, thene elsesão programas separados aqui?

$ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi

Esta pergunta não é sobre ponto e vírgula.

Maxim Koretskyi
fonte
2
Possível duplicata de ponto-e-vírgula em estruturas condicionais
Stephen Rauch
1
@StephenRauch Não é realmente uma duplicata. Além disso, é um resultado razoável desse Q, como uma tentativa de entender melhor.
Gypsy Spellweaver
Mais formulação programm-y:[ $variable == abcdef ] && echo yes || echo no
Hagen von Eitzen
2
@HagenvonEitzen que não é estritamente equivalente; se a instrução dentro do primeiro ramo falhar, o segundo também será executado.
Morgen
Possível duplicata de Quais são os operadores de controle e redirecionamento do shell?
G-Man diz 'Reinstate Monica'

Respostas:

26

As ;instruções separam (falando vagamente). É (quase) sempre possível substituir a ;por uma nova linha.

Dizer que ;separa dois programas, portanto, ife thendeve ser "programas" é um pouco simplista, pois pode ser feita uma declaração de palavras reservadas, funções de shell, utilitários internos e externos, e combinações destes usando pipes e operadores booleanos, etc. etc.

Ambas ife thensão palavras reservadas na gramática do shell , não "programas". Aqui eles são usados ​​para criar o que é tecnicamente chamado de comando composto .

echoé provavelmente um utilitário embutido no shell (mas não precisa ser) e lsprovavelmente um utilitário externo (ou "programa", como você diz).

Kusalananda
fonte
7

Embora essa seja uma boa primeira aproximação quando se está começando a aprender o básico do uso de shells, no nível de "aqui é como se executa um programa" e "aqui é como se executa vários programas um após o outro em uma única linha" , na verdade não é verdade.

O mais difícil de entender para uma iniciante, mas a explicação mais correta é que a linguagem shell é uma linguagem de computador . Tem uma sintaxe . Essa sintaxe compreende vários elementos lexicais, incluindo (entre outras coisas) novas linhas, operadores, palavras e palavras reservadas.

if, then, else, E fisão todas as palavras reservadas . Eles têm significados particulares ao analisar a entrada que se dá a um shell, de acordo com sua gramática . Da mesma forma, ;é um operador separador .

A entrada na linguagem shell é, assim, tomada como um todo, um programa de computador que é interpretado por outro programa, um intérprete , o shell. Suas partes gramaticais individuais não são programas. A linguagem do shell é uma maneira de especificar (outros) programas para o shell executar.

[não é um elemento lexical especial na gramática do shell, como um operador. É uma palavra comum , que nomeia um desses programas chamado [. Muitas conchas têm um built-in versão deste programa, combinado no código do próprio programa shell, mas você também pode encontrar um externo programa com esse nome em algum lugar, como /bin/[ou /usr/bin/[, quais os programas que não sejam conchas pode invocar. Da mesma forma, ]também não é um elemento lexical de shell especial. É uma palavra comum, que se torna um argumento para o [programa. O [programa requer que seu argumento final, quando executado, seja ], o qual ele passa a ignorar.

Outro programa semelhante chamado em sua pergunta é echo. Novamente, a maioria dos shells possui uma versão interna deste programa. Mas, novamente, há também uma versão externa do programa, em algum lugar como /bin/echoou /usr/bin/echo, para programas que não sejam shells para invocar.

Um terceiro programa nomeado em sua pergunta é ls. Os shells geralmente não têm versões internas deste programa, e é um programa externo, que pode ser encontrado em algum lugar como /bin/lsou /usr/bin/ls.

Para o shell Bourne Again, você pode ler mais sobre isso nos Recursos Básicos do Shell da documentação de informações do shell do GNU Bourne Again. Outras conchas têm gramáticas diferentes, naturalmente. A Especificação Unix Única descreve uma sintaxe à qual todos os shells compatíveis com POSIX (em seus modos compatíveis com POSIX) devem aderir.

Leitura adicional

  • " Gramática da casca ". Linguagem de Comando do Shell . Especificações básicas Edição 7. O grupo aberto. IEEE 1003.1-2008. ISBN 1937218812.
  • test. Utilitários . Especificações básicas Edição 7. O grupo aberto. IEEE 1003.1-2008. ISBN 1937218812.
  • " Gramática da casca ". O Manual Z Shell . versão 5.3.1. 2017.
JdeBP
fonte
5

Ele realmente não é muito forçado a pensar if, thene elsecomo programas externos. De fato, o shell Thompson na 1ª edição original do Unix implementou ife gotocomo programas externos. Isso é possível porque o subprocesso compartilha os descritores de arquivo com o processo do shell, portanto, um (encaminhamento) precisa apenas ler a entrada até encontrar o rótulo de destino e depois sair. Veja Thompson shell .

Johan Myréen
fonte
Ou, de fato, veja Laurent Bercot ife ifelse, do qual fazem parte execline. Estes não estão ifna questão, no entanto.
JdeBP
2
"Na verdade, não é exagero pensar em se, então e em outros, como programas externos" Bem, é, porque não são.
Lightness Races com Monica
2

Os programas thene elsenão são. As outras partes são. Observe que não há ;'diretamente atrás deles, mas após o comando que eles precedem.

O [ ... ] é um comando e precisa do ;if seguido pelo início de outro comando.

O AFAIK, todas as estruturas de controle no Bash e provavelmente a maioria dos shells * nix, são iguais. São instruções para o intérprete. O teste ou condição, por outro lado, utiliza um programa / processo que é "executado" e são comandos. Como thenfaz parte da linha que leva ao echocomando, ele deve ser separado por uma nova linha do comando anterior [ ... ]. Não precisa ser separado do comando que controla, o echo yes.

Legalmente, embora seja feio e difícil de ler, você também pode fazer isso.

if [ $VARIABLE == abcdef ]
then echo yes
else echo no
fi

Observe que não há necessidade de ;entre os controles aqui, mesmo que eles não estejam na sua própria linha.

Curiosamente, toda a estrutura de controle ( if ... fi) é um comando shell e a totalidade deve terminar com uma nova linha ou a ;. A última linha não pode ser, fi echo donemas deve ser fi; echo done. O mesmo que uma atribuição VARIABLE='abcdef'é um comando.

Mesmo que todas as estruturas de controle sejam comandos, elas ainda não são programas.

Tecelão de Magia Cigano
fonte
1

if, elif, then, E fisão todas as palavras-chave reservadas usadas para implementar uma das construções referido como um comando composto com casca, o que significa que não pode haver um comando (ou melhor, um outro comando) por qualquer um desses nomes em shell. O objetivo ;geral não é separar comandos, mas encerrar uma lista de comandos . Por exemplo, a seguir é uma ifdeclaração válida :

if echo foo; echo bar; echo baz; then echo done; echo really done; fi

A condição da ifinstrução é a lista de comandos echo foo; echo bar; echo baz. O analisador sabe que a condição acabou porque then, que segue imediatamente um ponto-e-vírgula, não pode ser um comando porque é uma palavra-chave reservada. Assim, sabe que o que se segue then é o começo do corpo. Da mesma forma, fié uma palavra-chave reservada e, portanto, não pode ser um terceiro comando no corpo da ifinstrução, mas marca o final do comando composto.

chepner
fonte
obrigado, se isso for usado if program1 foo; program2 bar; program3 baz; , qual status do programa deve ser 0, para que o shell continue then? O último?
Maxim Koretskyi
Apenas program3 baz. O status de saída de uma lista de comandos é o status de saída do último comando nessa lista. Os outros dois podem falhar sem afetar a condição.
chepner