Entendendo o ponto de exclamação (!) No bash

108

eu usei

history | less

para obter as linhas dos comandos anteriores e, a partir dos números do lado esquerdo, encontrei a linha que queria repetir (por exemplo, 22) e fiz

!22

no prompt de comando e funcionou - executando o conjunto de comandos na linha que fiz naquele momento. Não consigo descobrir onde o ponto de exclamação é usado, o que ele representa em termos de ações executadas pelo bash e onde usá-lo. Na documentação, não vejo uma explicação que seja 'tangível'.

Vass
fonte
6
Esta resposta pode ajudar
Michael Mrozek
9
Não é uma resposta para sua pergunta, mas <ctrl> + R permitirá que você pesquise interativamente seu histórico e execute imediatamente se encontrar o que estava procurando.
Kasterma #

Respostas:

144

!é um recurso que apareceu originalmente no shell C , antigamente, antes que você pudesse contar com terminais para ter teclas de seta. É especialmente útil se você adicionar o número do comando atual ao prompt ( PS1="\!$ ") para poder olhar rapidamente para a tela para obter números dos comandos anteriores.

Agora que você pode usar as teclas de seta e coisas como Ctrl-Rpesquisar no histórico de comandos, não vejo muita utilidade para o recurso.

Uma variante dele que você ainda pode achar útil é !!, que reexecuta o comando anterior. Por si só, não encontro !!Enternada mais rápido do que apenas Enter, mas pode ser útil quando combinado em um comando maior.

Exemplo: Um erro piloto comum em sudosistemas baseados é esquecer o sudoprefixo em um comando que requer privilégios extras. Um iniciante redigita o comando inteiro. O aluno diligente edita o comando a partir do histórico de comandos do shell. O iluminado digita sudo !!.

O Bash permite desativar o !processamento no shell com set +o histexpandou set +H. Você pode desativá-lo no Zsh com set -K.

Warren Young
fonte
4
Acho Ctrl-P Ctrl-J muito rápido; mais rápido que Up Enter, pelo menos.
ephemient 5/11/10
24
Se você deseja apenas executar o último comando, Up / Enter está bom, mas se você deseja adicioná-lo de alguma forma (digamos, você esqueceu sudoou algo assim), pode fazê-lo sudo !!, por exemplo. Isso pode ser um pouco mais rápido que "Up / Ctrl-A (ou Home, se você tiver sorte o suficiente) / sudo / space / enter". YMMV. :)
1
@AquariusPower: Apenas cite. Ou echo 'Hi!'ou echo "Hi!"ou echo Hi\!. Todos fazem a mesma coisa.
21813 Warren Young
1
setopt NO_BANG_HISTno zsh pode ser mais memorável que -K.
gregory
48

Se não houver uma resposta mais longa aqui, certamente haverá uma no Superusuário, já que li uma recentemente. Na página de manual do bash, você pode encontrar uma seção enorme intitulada EXPANSÃO DE HISTÓRIA sobre o assunto.

Você pode executar um host inteiro mais do que apenas executar o último comando ou o número de comando X. Você pode !catexecutar ações como executar o último comando iniciado com cat. Ou !?bash?:s/bash/csh/executa o último comando que contém, bashmas o substitui por csh.

Cry Havok
fonte
3
Embora não seja diretamente uma resposta à pergunta do OP, isso precisa de muito mais votos. Tão útil! Obrigado, Havok.
malvim
Eu realmente deveria olhar a página de manual antes de começar a pesquisar no Google.
31515 Erikbwork
1
!!:s/bash/csh/realmente executa o último comando e substitui o bash pelo csh, se presente. Não é o último comando que incluiu o bash. Isso seria !?bash?:s/bash/csh/ou talvez!?bash?:s/%/csh/
cde 24/01
Tendo usado o Bash extensivamente por vários anos, fiquei chocado ao descobrir que nunca tinha conhecido essa palavra-chave antes e, embora tenha passado horas vasculhando as manpáginas, esse recurso é incrivelmente obscuro. Obrigado por apontar a seção relevante - esse é o único lugar nos documentos reais em que eles explicam suficientemente.
Steve Benner 30/01
39

Muito mais pode ser feito com !:

  • execute um comando digitado antes de 3 comandos: !-3
  • execute um comando que comece com !ls

e muito mais. Veja 15 exemplos de expansão do histórico de Linux Bash que você deve conhecer

user379997
fonte
Votou isto. Nenhuma das outras respostas teve nenhum desses truques inteligentes.
Gergely Lukacsy
Promovido porque www.thegeekstuff.com é simplesmente um recurso fantástico, e este foi um dos poucos artigos do Linux que eu não tinha visto antes. Muito útil.
Steve Benner 30/01
4

Um amigo meu me enviou este e-mail:

Faz parte da biblioteca de história do GNU. No bash, é usado para executar novamente os comandos no seu histórico. Se você quer ser hardcore, grep for history_expansion_char no bash-4.1 / lib / readline / histexpand.c para obter detalhes da implementação.

Vass
fonte
3

Claro que você pode fazer !!para reutilizar o último comando no shell bash. E depois há !$para reutilizar a última parte do seu último comando.

por exemplo, veja algum arquivo

less path/to/your/file.txt

Se agora você deseja editar o mesmo arquivo, pode !$obter apenas o caminho do último comando

vim !$
Teshan Shanuka J
fonte
1
Ah, eu esperava encontrar isso. Como ele se comporta com dois argumentos?
Jonathan
Apenas reutilizará o último argumento dos dois. $touch f1 f2e depois $vim !$avaliará$vim f2
Teshan Shanuka J