Como alterar rapidamente a primeira palavra em um comando Bash?

44

Gostaria de melhorar um pouco meu fluxo de trabalho com o Bash e percebo que muitas vezes desejo executar o mesmo comando em um executável diferente.

Alguns exemplos:

Git (onde eu gostaria de mudar rapidamente a segunda palavra):

git diff     foo/bar.c
git checkout foo/bar.c

Cat / rm (onde somente a primeira palavra deve ser alterada):

cat foo/is/a/very/long/path/to/bar.c
rm  foo/is/a/very/long/path/to/bar.c

Sei que posso pressionar Ctrl+ ae Delremover a primeira palavra, mas estou me perguntando se existe uma maneira mais rápida de fazer isso.

nowox
fonte
Honestamente, acho mais seguro usar Ctrl + ae excluir. Definitivamente, não é muito lento.
agweber

Respostas:

56

!$ expande para a última palavra do seu comando anterior.

Então você poderia fazer:

cat foo/is/a/very/long/path/to/bar.c

rm !$

ou:

git diff foo/bar.c

git checkout !$

Seus exemplos repetiram apenas a última palavra, então !$funcionaram bem. Se você realmente tinha muitos argumentos que desejava repetir e só queria alterar a primeira palavra, poderia usar o !*que se expande para todas as palavras do comando anterior, exceto o zeroth.

Veja a seção "HISTORY EXPANSION" da bashpágina de manual. Há muita flexibilidade lá.

Spiff
fonte
16
Certo e adequado. Gostaria apenas de colocar um aviso : com !$você não há controle visual completo da linha que está executando . Isso pode resultar prejudicial às vezes. Especialmente se você tiver um erro de impressão. É preciso do historyque expandir. Portanto, se você escrever o último comando com um espaço em branco no início, provavelmente esse comando não será concluído no histórico. Quando você executará seu novo comando com !$o shell, não pegará os parâmetros da última linha de comando digitada, mas apenas do último da história. Aqui mesmo mais palavras.
Hastur 22/01
1
@ Hastur Você pode configurar seu shell para expandir o histórico na guia ou ao entrar para evitar acidentes.
slhck
2
@Hastur É por isso que você precisa pressionar introdução duas vezes em zsh (promoção descarada)
Braiam
@Hastur - Quando tenho alguma dúvida sobre o que vai acontecer ou, tardiamente, percebo que tenho que fazer outra coisa antes de executar alguma coisa que acabei de digitar, vou para o início da linha e adiciono um #ou um echo para que eu possa vê-lo e entrar na história para que eu possa recuperá-lo e executá-lo novamente sem o prefixo de desativação.
Joe
28

Ctrl+ apara ir para o início da linha e, em seguida, Alt+ dpara excluir a primeira palavra.

jjlin
fonte
9
O atalho da palavra excluir é na verdade Meta + d, e o Meta geralmente é mapeado para o Alt em máquinas Linux. Em plataformas onde esse não é o caso, uma alternativa para obter o modificador Meta é usar o Escape como prefixo. Veja en.wikipedia.org/wiki/Meta_key
Gustavo Giráldez 22/15/15
2
@ GustavoGiráldez se você quiser ir fundo, Meta+Dsó será válido se emacsestiver ativado (via set -o emacsou simplesmente por padrão). Não funcionará no modo de editor inferior ou se emacsestiver desativado.
TC1 23/01
Em muitos terminais (porque isso é uma coisa do terminal e não uma coisa do Bash), a tecla home também irá para o início de uma linha. Muitos laptops mapeiam Fn + Esquerda para a tecla Home. Da mesma forma, a tecla Encerrar normalmente irá para o final da linha. Eu ainda tenho que usar um emulador de terminal que não suporta essas teclas de atalho.
Kat
1
@ Mike Por outro lado, C-ae M-dé muito mais rápido digitar se suas mãos já estiverem na posição de digitação.
Jjlin
@ Mike Isso é uma coisa bash. Digite cate compare o que você obtém ao pressionar Início ( ^[[Haqui) e ao pressionar Ctrl + a ( ^A).
Jonas Schäfer
17

Não tenho certeza se seria realmente mais rápido ou não, mas consulte este artigo, especialmente o ponto # .3:

  1. Substitua uma sequência do comando anterior usando ^ str1 ^ str2 ^

No exemplo a seguir, primeiro executamos o comando ls para verificar um arquivo. Mais tarde, percebemos que queremos visualizar o conteúdo do arquivo. Em vez de digitar o nome do arquivo inteiro novamente, podemos apenas substituir os "ls" no comando anterior por "cat", como mostrado abaixo.

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate
Benguin
fonte
15

Alt+.

Se você precisar apenas repetir a última parte de um dos comandos anteriores, poderá usar Alt+ .que colará o último argumento obtido da última linha do histórico.

Se pressionado mais de uma vez, substituirá o que acabou de ser colado com o último argumento da linha antes ...

Por exemplo, se os últimos 2 comandos foram:

cat foo/is/a/very/long/path/to/bar.c
pico foo/is/a/very/long/path/to/SomeWhereElse.c

No shell eu escrevo rme pressiono Alt+ .ele aparecerá:

rm foo/is/a/very/long/path/to/SomeWhereElse.c

se eu pressionar novamente Alt+ .ele aparecerá

rm foo/is/a/very/long/path/to/bar.c

e assim por diante...

Hastur
fonte
Não sei por que, mas isso não funciona no meu console Mac.
Lulalala 27/03
Aqui estão os atalhos de teclado conhecidos por trabalhar bash. BTW Tem certeza de que está usando o bash como shell ?
Hastur
1
Eu acho que isso é uma coisa do Mac. Quando digito que recebo
lulalala 27/03
12

Além da resposta @jjlin, você pode estar interessado nas seguintes dicas:

  • Ctrl+ wexclui a palavra à sua esquerda
  • Ctrl+ kexclui do cursor até o final da linha de comando
  • Ctrl+ uexclui do cursor até o início da linha de comando
  • Alt+ bmove o cursor uma palavra para trás
  • Alt+ fmove o cursor uma palavra para frente
  • $_ contém o último argumento da linha de comando anterior

Para obter mais informações, consulte a seção "Readline Command Names" da página de bashmanual.

por exemplo:

cat foo/is/a/very/long/path/to/bar.c
rm $_
maiki
fonte
Essas são ótimas dicas, mas não respondem à pergunta.
slhck
@slhck IMHO, porque o título da pergunta não corresponde aos exemplos fornecidos. Se focarmos nos exemplos, como eu fiz, o título deve ser "Como alterar rapidamente uma palavra em um comando bash?" . É também por isso que minha resposta é "além da de @jjlin". Mas acho que a questão deve ser esclarecida.
maiki
O OP sempre deseja remover (trocar) as primeiras npalavras do comando, n = 1no primeiro exemplo e n = 2no segundo. A resposta de jjlin mostra como excluir a primeira palavra (e reaplicando o atalho, exclua até as npalavras). Sua resposta lista alguns atalhos do Bash (que são realmente úteis), mas nenhum deles é uma maneira eficiente de excluir as primeiras npalavras.
slhck
Hm, lendo novamente, o $_parâmetro provavelmente funcionaria se houvesse apenas um argumento (ou seja, n = m - 1onde mé o número total de argumentos). O restante dos atalhos é irrelevante para a questão.
slhck
@slhck Por uma questão de argumentação, eu li o primeiro exemplo como "substituir a segunda palavra" :-)
maiki
8

Se você é proficiente em vi, você pode ativar vi ligações em bash (a maioria das conchas?) Usando o comando set -o vi. Em seguida, você pode usar as teclas vi normais para editar seu comando. No seu primeiro exemplo, você pode ^wcwexcluir "diff" e alterá-lo para checkout.

Pode não valer a pena aprender as combinações de teclas do vi apenas para editar a linha de comando, mas se você já as conhece, é um ótimo aumento de produtividade.

Chaosed0
fonte
Eu aprendi em kornshell, assim set -o vicomo eu vivia! Eu também faço isso nos meus prompts do bash.
precisa saber é o seguinte
bindkey -vpara zsh. Esc 0 c w
user530873
6

Existem muitas maneiras de esfolar esse gato!

Para substituir uma sequência específica, ^old^new^extraexecute o comando anterior, substitua oldpor newe acrescente extra. Você pode parar o quanto quiser; por exemplo ^old, substituirá olda sequência vazia e acrescentará a sequência vazia (essencialmente excluindo olde não fazendo mais nada).

1. ^diff^checkout
2. ^cat^rm

Variante especialmente útil disso:

for i in `seq 1 10`; do echo something complicated; done
# inspect the output to see if it looks right
^echo

Para substituir uma palavra específica, você pode usar !m:n-ppara se referir às palavras natravés pdo comando m(números negativos uso de contar para trás a partir do comando atual). Você pode omitir a -pparte para se referir a uma única palavra e omitir a :m-pparte para se referir a um comando inteiro. Formulários especiais !!para !-1, !$para a última palavra do comando anterior e !*para os argumentos (exceto a palavra 0) do comando anterior são bastante úteis.

1. !!:0 checkout !!:2-
2. rm !*

Costumo usar os dois; O zsh é especialmente bom aqui, pois pressionar a tecla tab expandirá as coisas enigmáticas para garantir que você esteja certo.

Também existem muitas maneiras de fazer isso com a edição de linhas. Leia as combinações de teclas do seu shell.

Daniel Wagner
fonte
-2

A maioria dos programas de terminal suporta ...

  • Pressione <Up-Arrow>conforme necessário para exibir novamente uma das linhas de comando anteriores do histórico.
    • Pressione <Down-Arrow>conforme necessário para avançar na lista de histórico.
  • Pressione <Left-Arrow>conforme necessário para mover o cursor até o final da segunda palavra.
  • Pressione <Backspace>conforme necessário para apagar a segunda palavra.
  • Digite a segunda palavra de substituição.
    • Pressione <Right-Arrow>/ <Left-Arrow>conforme necessário para reposicionar para mais alterações.
  • Pressione <RETURN>para executar o comando

Se a linha de comando que você deseja não for recente, faça uma pesquisa inversa com a <Ctrl-r>descrição em questão ...
Existe uma maneira de usar ctrl-r depois de digitar parte do comando no bash?
Em seguida, edite através das teclas de seta, conforme necessário.

DocSalvager
fonte
-3

O que eu faço (Ubuntu / bash):

1) Arrow upei para retornar o comando anterior
2) Hometecla para retornar ao início
3) Modifique o comando conforme necessário.

À prova de idiotas e especialmente útil para comandos de várias linhas.

Vorac
fonte