Lembre-se de um comando digitado pela metade enquanto eu verifico algo

97

Costumo me encontrar na seguinte posição: comecei a digitar um comando longo no prompt do bash, mas, no meio do processo, descobri que precisava verificar algo com outro comando. Esse é um problema quando estou no console (sem X), o que geralmente acontece, porque só tenho as seguintes maneiras insatisfatórias de fazer isso, que eu conheço:

  • Pressione ctrl+ alt+ F2e faça login em outro console virtual e descubra o que eu queria, depois volte e continue
  • ctrl+ a, digite echo + space+ enter, descubra o que eu queria, pressione até encontrar meu comando, ctrl+ a, delx 5, ctrl+ ee continue
  • Destaque o que eu digitei até agora com o mouse (se o gpm estiver em execução, o que geralmente é), pressione ctrl+ cpara interromper, descubra o que eu queria enquanto tomava cuidado para não usar o mouse para destacar coisas e pressione o botão do meio do mouse em um novo prompt e continue
  • Ore aos deuses da linha de comando para que o comando semi-escrito não tenha efeitos adversos, mas simplesmente falhe, e pressione com cuidado enter, depois descubra o que eu queria, pressione para cima até recuperar meu comando e continue
  • Entre na minha máquina do tempo, viaje de volta no tempo e lembre-me de começar a tela antes de começar a digitar comando, voltar ao presente, pressionar ctrl+ a c, descobrir o que eu queria, pressionar ctrl+ a ctrl+ae continuar

Então, o que eu quero saber é: existe alguma maneira mais elegante de fazer isso? Uma espécie de subshell-command ou similar?

Estou mais interessado em métodos que não exigem nenhuma preparação ou configuração para funcionar.

Lauritz V. Thaulow
fonte

Respostas:

68

Uma versão um pouco mais rápida do Ctrl + A Ctrl+ de alexK (que se move para a frente da linha e depois corta tudo para a frente) é apenas usar Ctrl+ U, que corta para trás no bash e toda a linha (independentemente da sua posição atual) no zsh. Então você usa Ctrl+ Ypara colar novamente

Michael Mrozek
fonte
1
Testando isso, concluo que Ctrl + U não recua e recua, mas recua. Ter o cursor no meio do comando deixa o que está por trás dele na linha de comando. No entanto, ainda há uma melhoria de 33% em relação à solução da @ alex, pois economiza o pressionamento de tecla.
Lauritz V. Thaulow
2
@ Lazyr Oh, muito bem; em zshque o corta toda a linha, mas no bashcorta para trás. Eu nunca notei essa diferença antes
Michael Mrozek
2
Ah, eu não sabia que Ctrl + U também coloca texto para matar o buffer. Bom saber! :)
alex
1
^U ^Která o mesmo efeito, ^A ^Kmas é marginalmente mais ergonômico e significativamente mais conveniente screen.
intuited
53

Pressione Ctrl-A para chegar ao início da linha, adicione um hash e pressione return - dessa forma, ele permanecerá no histórico de comandos como um comentário e você poderá voltar com o cursor para cima

EDIT: apenas notei que esta é uma variante um pouco mais elegante no seu # 2;)

jamespo
fonte
1
Sim, e por que não pensei nisso? Obrigado!
Lauritz V. Thaulow
1
Preciso ler antes de postar minha própria resposta. James está certo.
Sean C.
4
Observe que isso não funcionará cshou zshporque eles não permitem comentários no shell interativo. Em zshque você precisa para ativar a opção adequada: setopt interactive_comments.
sam Hocevar
1
@Sam Sim, mas ": comando" tem o mesmo efeito ( ":" = o comando null)
barrycarter
6
@ barrycarter: não, :deve ser considerado prejudicial para esse fim e nunca, jamais, sugerido. Ele executará tudo após um ponto-e-vírgula, dentro de backticks etc. com todos os efeitos colaterais associados.
Sam Hocevar
29

Pressione Ctrl+A, Ctrl+Kpara ir para o início da linha e exclua (mate) até o final. Em seguida, faça sua pesquisa e, quando estiver pronto para continuar, pressione Ctrl+Y(puxar) para colocar sua linha salva (morta) de volta.

alex
fonte
3
Ah, agora isso é mais parecido com o que eu tinha em mente. E eu faço isso o tempo todo no Emacs, deveria ter pensado em fazer o mesmo na linha de comando.
Lauritz V. Thaulow
13

No zsh, digite Ctrl+ Zpara "suspender" o comando que estou digitando e digite outro comando. Depois de executar esse comando (ou abortá-lo com Ctrl+ C), o comando suspenso volta para edição (mesmo lembrando a posição do cursor). Como conveniência adicional, se a linha de comando estiver vazia quando eu digitar Ctrl+ Z, a tecla chamará o interno bg(portanto, um duplo Ctrl+ Zenvia um comando em execução diretamente para o plano de fundo).

fancy-ctrl-z () {
  emulate -LR zsh
  if [[ $#BUFFER -eq 0 ]]; then
    bg
    zle redisplay
  else
    zle push-input
  fi
}
zle -N fancy-ctrl-z
bindkey '^Z'          fancy-ctrl-z

Eu não sei como fazer algo semelhante no bash.

Em qualquer shell, você pode usar o método de baixa tecnologia para adicionar um #no início da linha atual .

Gilles
fonte
2
sua função é admirável, mas você sabia que zshtem uma função para que construído em já ? É chamado push-linee tudo que você precisa fazer é usá bindkey-lo para alcançá-lo.
Caleb
@ Caleb: Não sei por que uso, push-inpute não push-lineaqui, push-lineparece mais apropriado (talvez as versões antigas do zsh só tivessem push-input?). Mas isso não substitui o restante da função.
Gilles
Tanto quanto posso dizer, a única diferença é o mesmo efeito vinculativo em segundo plano um trabalho em execução. Estou esquecendo de algo?
Caleb
1
@Caleb: Não, é só que eu acho a combinação dos dois conveniente ( push-lineé inútil em uma linha vazia, bgparticipar Ctrl+Zsó é útil quando acabei de suspender esse processo Ctrl+Z) e mnemônico (estou em segundo plano no processo ou a linha de comando parcial).
Gilles
3
@Caleb push-inputsuspende todo o buffer de entrada, enquanto push-linesuspende apenas a linha atual. Se eu estiver digitando um comando com várias linhas, quero suspender o comando inteiro, então push-inputé o correto. Acho push-inputmais útil do que push-line(se eu quiser atrasar uma linha em um buffer de entrada com várias linhas, posso simplesmente navegar até o início da linha e inserir uma nova linha), então, na verdade, me pergunto por que push-linerecebi a tecla de atalho padrão e não push-input.
Gilles
13

No bash, basta digitar Alt+ #.

Em seguida, quando estiver pronto, pressione Upem seguida, Alt+ #.

O primeiro coloca um #no início da linha para transformá-lo em um comentário e depois aceita a linha, como se você tivesse pressionado Enter.

Então, quando você faz uma segunda vez, ela vê que a linha já tem uma #no início, então a remove e a aceita, novamente salvando a Enterchave.

Se a segunda vez inserir outra #, basta digitar Alt+ - Alt+ #.

Você pode fazer o zsh fazer o mesmo colocando

bindkey -M emacs '\e#' pound-insert

no seu ~ / .zshrc.

Ou, se você estiver usando ligações do vi, poderá digitar #no modo de comando no bash e no zsh.

Mikel
fonte
2
Não funciona para mim, o segundo comando destinado a remover o # apenas adiciona mais # à frente.
Lauritz V. Thaulow
1
O primeiro funciona? Qual versão do bash você está usando?
11117 Mikel
3
Alt + # funciona como você descreve em seu terceiro parágrafo, mas não como em seu quarto, ele simplesmente adiciona outro # à frente e aceita a linha. Eu uso o bash 4.1.5 (1) -release no Ubuntu 10.10.
Lauritz V. Thaulow
1
Oh querido, no bash requer um argumento numérico, por exemplo, Esc+1então Alt+ #para alternar.
Mikel
Isso funciona, mas é muito mais complicado do que apenas Ctrl + A Del Ctrl + E, especialmente no layout do meu teclado, onde Alt + # é na verdade Alt + Shift + 3.
Lauritz V. Thaulow
10

Um dos meus recursos favoritos zshé a função de linha de push integrada que cuida disso sem nenhuma das invasões das outras respostas aqui. Eu o vinculei a Ctrl+ lno meu .zshrcarquivo assim:

bindkey '^L' push-line

Então, quando estou digitando algum comando e preciso fazer outra coisa rapidamente, posso invocá-lo com uma tecla e obter um prompt em branco. Depois de executar o outro comando, o prompt é preenchido automaticamente com o que eu estava digitando antes.

Você pode encadear várias camadas disso e os comandos retornarão para você na ordem inversa em que você os empurrou para a fila.

Caleb
fonte
5
Limite para Ctrl+Qe ESC qpor padrão (no modo emacs).
Gilles
Existe algo semelhante para o bash?
Magnus
@ Magnus: Por favor, reveja o restante das respostas sobre esta questão. Existem soluções para o bash, mas não tão elegantes quanto isso.
Caleb
@ Caleb, eu deveria ter sido mais específico, existe uma combinação de teclas única semelhante para o bash?
Magnus
1
Esta é claramente a resposta "correta", para o Zsh de qualquer maneira! Eu só quero mencionar o push-line-or-editwidget, que não está vinculado a nenhum mapa de teclas por padrão. No prompt de nível superior, ele faz a mesma coisa que push-line, mas em qualquer nível de prompt abaixo, converte o comando inteiro sendo inserido em um buffer de várias linhas. Duas ótimas funções em uma combinação de teclas! Eu posso recomendar ligação em push-line-or-editvez de simples push-line. Você não perde nada e ganha funcionalidade útil.
Wjv 5/04
5

Além do truque ctrl- a ctrl- k, se você estiver na tela, apenas ctrl- a dpara desconectar e reconectar comscreen -r

Você também pode simplesmente abrir outra janela com ctrl+a c

Warren
fonte
8
Se você estiver na tela, basta abrir outra janela com Ctrl+A c.
Gilles
1
@ Gilles .. a menos que você precise usar algum aspecto do estado do shell (variáveis, funções, aliases, etc.).
intuited
4

Uma maneira alternativa, porém não perfeita, pressione Ctrl-X Ctrl-E. Isso abrirá seu editor padrão contendo seu comando meio digitado. Em seguida, você pode salvar seu comando em um arquivo ou abrir um novo shell a partir do seu editor. Quando você sair do novo shell, ele retornará ao editor e o salvamento do conteúdo os executará automaticamente.

Isso não é perfeito porque não retorna ao seu shell original, mas força a execução do comando ou o descarta completamente. Mas não há seleções temporárias ou buffers de interrupção com os quais se preocupar, e também existem alguns ajustes interessantes, por exemplo, se editor = vi

:wq            # execute the command
:cq            # cancel and abort
:! command     # execute command
:shell         # open a new shell
:r filename    # insert the contents of a file for editing
:r ! command   # insert the output of a command for editing
forcefsck
fonte
Alternativa muito boa. Sou independente do vi-emacs, por isso ficarei feliz em usar essa ferramenta quando as ferramentas elétricas forem realmente necessárias. (.. Falando de vi, eu tentei o linux emulador de N64 mupen64plus um tempo atrás Esc sai do emulador sem salvar eu logo desistiu de jogar qualquer coisa.)
Lauritz V. Thaulow
1
@lazyr, para o debian / ubuntu execute sudo update-alternatives --config editore escolha seu editor favorito. Para outros sistemas, defina as variáveis ​​de ambiente EDITOR ou VISUAL para o seu editor favorito, por exemplo, adicione export EDITOR=/usr/bin/nanoseu .bashrc.
forcefsck
3

Semelhante ao método de adição #no início da linha, existe um método sem dúvida mais simples que eu uso, que não requer retorno ao início da linha:

Basta adicionar uma cotação aberta e não fechá-la, seja simples ou dupla.

Então pressione Enter.

Então pressione CtrlC.

O comando parcial é salvo no histórico de comandos (disponível via seta para cima), mas na verdade não é executado.

Curinga
fonte
2

Usando zsh, se você digitar <ESC> q(escape e Q), sua linha de prompt será cortada, para que você possa digitar outro comando. Você receberá automaticamente seu texto cortado no próximo prompt.

Ele pode lembrar várias linhas ao mesmo tempo, para que você possa usá-lo enquanto uma linha estiver esperando por você. Você pode até usá-lo na linha em branco para atrasar o resumo da sua linha de corte.

Não é a maneira mais eficiente se você precisar usar vários comandos para a verificação / preparação (você precisará digitar novamente <ESC> qantes de cada comando). Mas acho que é possível vinculá-lo a um atalho mais curto.


Se você quiser apenas verificar o manual, digite <ESC> h(escape e H). Isso executará o run-helpbuilt-in, com a primeira palavra da linha de comando como argumento. Você voltará a sua linha intacta quando terminar.

loxaxs
fonte
A maioria dos terminais permite fazer isso em M-qvez de<ESC> q
sleblanc 26/09