Expansao de Historico: Reutilizando Comandos com !! e !$

Expansao de Historico: Reutilizando Comandos com !! e !$

O Que Voce Vai Aprender

  • Que a expansao de historico e uma "sintaxe para recuperar comandos passados"
  • Como reutilizar um comando ou argumento instantaneamente com !! / !$
  • Como extrair itens especificos do historico com !string / !:n / :h :t :r
  • Como a substituicao rapida ^old^new^ funciona, e como se manter seguro com histverify
Lina: Linny-senpai, eu continuo vendo coisas como sudo !! e cd !$. O que e essa marca !?
Veterano Linny: Isso e "expansao de historico," um recurso do bash. Quando voce digita uma sintaxe que comeca com !, o bash recupera um comando ou argumento passado para que voce possa reutiliza-lo. Economiza muita digitacao.

1. O Que e Expansao de Historico?

Conclusao: A expansao de historico e um recurso do bash que expande a sintaxe ! em um comando ou argumento passado, reduzindo digitacao e erros de reentrada.

Lina: O que "expansao" realmente significa?
Veterano Linny: Antes de executar um comando, o bash substitui sintaxes como !! pelo texto real do comando. Por exemplo, !! se expande para seu comando anterior inteiro.

A expansao de historico e construida a partir de tres tipos de partes.

Parte Funcao Exemplo
Event designator Qual comando recuperar !! / !42
Word designator Qual palavra desse comando extrair !$ / !^
Modifier Como transformar a palavra extraida :h / :t

A expansao de historico funciona principalmente no shell bash interativo. Ela e desativada por padrao dentro de scripts, entao lembre-se: "util interativamente, mas nao escreva em scripts."

2. Event Designators: Qual Comando Recuperar

Conclusao: !! e o comando anterior, !n e o numero n do historico, !string e o comando mais recente que comeca com string, e !?string? e o mais recente que contem string.

Lina: Entao primeiro eu escolho "qual comando recuperar."
Veterano Linny: Certo. O mais comum e !!, o comando anterior. E o truque classico quando voce esqueceu o sudo.

!! -- O Comando Anterior Inteiro

$ apt update
E: Could not open lock file /var/lib/dpkg/lock-frontend ...

$ sudo !!
sudo apt update

!n / !-n -- Por Numero do Historico

$ history | grep tar
  765  tar -czf backup.tar.gz /etc

$ !765
tar -czf backup.tar.gz /etc

!n recupera o numero n do historico, e !-n recupera "n comandos atras" (!-1 e o mesmo que !!).

!string -- Comando Mais Recente que Comeca com string

$ !ssh
ssh user@server

!string re-executa o comando mais recente que comeca com string.

!?string? -- Comando Mais Recente que Contem string

$ !?server?
ssh user@server

!?string? encontra o comando mais recente que contem string em qualquer lugar, nao apenas no inicio. Essa e a diferenca em relacao ao !string.

!string executa imediatamente sem confirmacao. Pode recuperar um comando mais antigo que voce nao pretendia, entao quando estiver em duvida, verifique o resultado primeiro com :p (apenas imprimir), coberto a seguir.

3. Word Designators: Extraindo Argumentos

Conclusao: !$ e o ultimo argumento, !^ o primeiro, !* todos os argumentos, e !:n a n-esima palavra. Eles evitam redigitar caminhos longos.

Lina: As vezes eu quero reutilizar apenas um argumento, nao o comando inteiro.
Veterano Linny: E para isso que servem os word designators. !$ e "o ultimo argumento do comando anterior," entao voce evita redigitar um caminho longo.

!$ -- O Ultimo Argumento

$ mkdir -p /var/log/myapp
$ cd !$
cd /var/log/myapp

!^ e !* -- Primeiro Argumento / Todos os Argumentos

$ cp config.yml config.yml.bak
$ vim !^
vim config.yml

!^ e o primeiro argumento, e !* e cada argumento exceto o nome do comando.

!:n -- A n-esima Palavra

As palavras sao numeradas a partir de 0, onde 0 e o proprio nome do comando.

$ cp src.txt dst.txt
$ echo !:1
echo src.txt
$ echo !:2
echo dst.txt
Word designator Significado
!^ Primeiro argumento (igual a !:1)
!$ Ultimo argumento
!* Todos os argumentos (!:1-$)
!:0 O proprio nome do comando
!:n A n-esima palavra
!:n-m Palavras de n ate m

!$ e similares implicitamente se referem ao comando anterior. Para extrair um argumento de um comando diferente, combine-os com um event designator, como !ssh:$.

4. Modifiers: Transformando a Palavra

Conclusao: :h e a parte do diretorio, :t o nome do arquivo, :r remove a extensao, :e mantem apenas a extensao, e :p imprime sem executar.

Lina: As vezes eu quero apenas o "diretorio" ou apenas o "nome do arquivo" de um caminho.
Veterano Linny: Os modifiers cuidam disso. Adicione :h ou :t apos um word designator para dividir um caminho em partes.
$ ls /var/log/syslog
$ echo !$:h
echo /var/log
$ echo !$:t
echo syslog
Modifier Acao Exemplo (/var/log/app.log)
:h head: remover o componente final (dir) /var/log
:t tail: manter apenas o componente final app.log
:r root: remover a extensao /var/log/app
:e extension: manter apenas a extensao log
:p print: mostrar a expansao apenas (sem exec) --

Use :p para Visualizar a Expansao

$ !ssh:p
ssh user@server

Com :p, a expansao de historico imprime o resultado sem executa-lo. A expansao e adicionada ao seu historico, entao voce pode revisa-la e depois executa-la com !!.

Ao recuperar comandos com rm ou sudo via !string, adquira o habito de verificar o resultado com :p primeiro para evitar acidentes.

5. Substituicao Rapida: ^old^new^

Conclusao: ^old^new^ re-executa o comando anterior com o primeiro old substituido por new. Perfeito para corrigir um erro de digitacao.

Lina: Quando eu digito errado apenas uma parte do comando anterior, redigitar tudo e irritante.
Veterano Linny: Use ^old^new^. Ele re-executa o comando anterior com old substituido por new. E a correcao padrao para erros de digitacao.
$ cat /etc/hosst
cat: /etc/hosst: No such file or directory

$ ^hosst^hosts^
cat /etc/hosts

^old^new^ e um atalho para !!:s/old/new/ e substitui apenas a primeira correspondencia. Para substituir todas, use !!:gs/old/new/.

O ^ final e opcional (^hosst^hosts tambem funciona). Mas se voce quiser adicionar mais texto apos a substituicao, escreva o ^ final explicitamente.

6. Mantendo-se Seguro com histverify

Conclusao: Com shopt -s histverify, a expansao de historico nao e executada imediatamente; ela se expande na linha de edicao para que voce possa confirmar antes de pressionar Enter.

Lina: Me assusta um pouco que !! execute sem confirmacao.
Veterano Linny: histverify resolve isso. Com ele ativado, o resultado expandido de !! aparece na sua linha de entrada primeiro, e nada executa ate voce pressionar Enter.

Adicione esta unica linha ao ~/.bashrc.

shopt -s histverify

Depois recarregue com source ~/.bashrc. A partir de agora, digitar !! ou !string mostra o comando expandido na linha de entrada para que voce possa revisar e editar antes de executar com Enter.

histverify e uma rede de seguranca contra executar comandos destrutivos por acidente. Se voce usa expansao de historico diariamente, ativa-lo traz tranquilidade.

7. Resumo

Conclusao: Combine as tres partes -- event designator, word designator e modifier -- para reutilizar comandos passados livremente.

Aqui esta um resumo rapido da sintaxe principal de expansao de historico.

Sintaxe Significado
!! O comando anterior inteiro
!n / !-n Numero n do historico / n comandos atras
!string Comando mais recente que comeca com string
!$ / !^ Ultimo argumento / primeiro argumento
!* Todos os argumentos
!$:h :t Diretorio / nome do arquivo de um caminho
^old^new^ Re-executar comando anterior, substituido
!!:p Imprimir a expansao apenas (sem executar)
Lina: Um ! oferece tantas formas de recuperar comandos! Vou comecar com !! e !$.
Veterano Linny: Isso e suficiente. Quando estiver confortavel, adicione !string e ^old^new^, e sua digitacao ficara cada vez mais rapida.

Proximas Leituras