O que a digitação de um único ponto de exclamação faz no Bash?

20

O Bash usa pontos de exclamação para expansões do histórico, conforme explicado nas respostas a esta pergunta (por exemplo, sudo !!executa a linha de comando anterior com sudo). No entanto, não consigo encontrar nenhum lugar que explique o que executar o seguinte comando (ou seja, um único ponto de exclamação):

!

Parece não imprimir nada e sair com 1, mas não sei por que isso acontece. Procurei on-line e na página de manual do Bash, mas não consigo encontrar nada, além do fato de ser uma "palavra reservada" - mas é o que ocorre }e executando o seguinte:

}

imprime um erro:

bash: syntax error near unexpected token `}'
Josh
fonte
11
Nada. !indica o "início" de uma expressão de expansão do histórico.
Jordanm #

Respostas:

47

O único !no início de um comando nega o status de saída do comando ou pipeline : se o comando sair 0, ele entrará em 1(falha) e, se sair diferente de zero, o transformará em uma 0saída (bem-sucedida).

Esse uso está documentado no manual do Bash:

Se a palavra reservada '!' precede o pipeline, o status de saída é a negação lógica do status de saída, conforme descrito acima.

Um !sem seguinte comando nega o comando vazio, que não faz nada e retorna verdadeiros (equivalentes para o :comando ). Assim, inverte o verdadeiro para falso e sai com o status 1, mas não produz nenhum erro.


Também existem outros usos !dentro dos comandos teste [[, nos quais eles negam um teste condicional. Eles não têm relação com o que você está vendo. Na sua pergunta e nesses casos, não está relacionado à expansão do histórico e !é separado de outros termos.

Michael Homer
fonte
5
+1 na primeira resposta para explicar o que realmente é executado e por que isso explica o código de retorno.
Jeff Schaller
11

Você pode encontrar o ponto de exclamação único documentado na seção 3.2.2.

Se a palavra reservada '!' precede o pipeline, o status de saída é a negação lógica do status de saída, conforme descrito acima.

$ ! true; echo $?
1
$ ! false; echo $?
0

Seção 3.2.4.2 - Construções Condicionais

! expressão

Verdadeiro se a expressão for falsa.


Também seção 4.1 Bourne Shell Builtins

! expr

Verdadeiro se expr for falso.


Também deve-se observar que !iniciará a substituição do histórico, a menos que seja seguido por: um espaço, tabulação, final da linha, '=' ou '(' (quando a opção extglob shell estiver ativada usando o shopt interno).

Jesse_b
fonte
0

Porque !é usado em comparações e significa NÃO .

Por exemplo:

a=3
b=2

[ $a -eq $b ] && echo "Equal"
[ ! $a -eq $b ] && echo "Not equal"
# of cause last comparison is possible to write as:
[ $a -eq $b ] || echo "Not equal"

[ $a -eq $b ]
echo $?
1
[ ! $a -eq $b ]
echo $?
0
Yurij Goncharuk
fonte
11
Esse é o significado de !um argumento para o testcomando (incluindo a versão interna do bash), não o significado de !quando usado na posição do comando.
Gilles 'SO- stop be evil'
11
Seria necessário ! [...]corresponder à pergunta neste caso.
Michael Homer
Concordou com @Gilles e @Michael Homer. Eu sabia que []sim test. Estou um pouco apressado.
Yurij Goncharuk
-2

! comando interno, inverte o sentido de um pipeline.

Outros usos:

#! comando interno, chama o intérprete nomeado para executar o script.

! designador de evento, marca uma palavra da linha de comandos como uma substituição do histórico

!= operador de desigualdade

$! variável shell, retorna o número do processo do último comando em segundo plano.

Bharat
fonte
Apenas para adicionar, pode-se usar! $ Para usar a última palavra do comando anterior da seguinte forma: ls -l /tmp cd !$ Isso o levará ao diretório / tmp.
Hopping Coelho
-3

! seguido por uma sequência executa o comando anterior mais recente (ainda no buffer de comando) iniciado com a sequência especificada. Talvez o shell tenha descoberto que nenhum comando anterior começou com <null>.

pdelmonte
fonte
3
Você notou que não havia uma string específica na pergunta ...?
Jeff Schaller