Procure um comando anterior com o prefixo que acabei de digitar

67

Podemos usar as setas para cima e para baixo para navegar no histórico de comandos.

Em alguns IDEs, como o Matlab, se introduzirmos algo e pressionarmos as teclas de seta, rolaremos apenas os comandos do histórico, começando pelo que inserimos. Isso é realmente conveniente, mas em um terminal shell, isso não funciona.

Existe alguma maneira de obter uma função semelhante em um terminal shell? E outras dicas para melhorar a eficiência no uso de terminais?

Lee
fonte
Você pode simplesmente usar um shell que forneça esse recurso, como fish;) #
23335
@yoann você está assumindo que o bash não. Por via readline, ele não é acessível por padrão.
muru 24/09/15
@muru Estou ciente de CTRL + R no bash, e a resposta da egmont fornece uma maneira elegante de fazer isso com Page Up / Page Down. Existe, no entanto, uma maneira de fazer isso com as teclas de seta?
precisa saber é
11
@yoann confira unix.stackexchange.com/a/76591/70524 . Em vez de \e[5~e \e[6~, utilização \e[A, \e[B.
muru

Respostas:

95

O que você está procurando é CtrlR.

Digite CtrlRe digite parte do comando que você deseja. O Bash exibirá o primeiro comando correspondente. Continue digitando CtrlRe o bash passará pelos comandos correspondentes anteriores.

Para pesquisar para trás no histórico, digite CtrlS. (Se CtrlSnão funcionar dessa maneira para você, isso provavelmente significa que você precisa desativar o controle de fluxo XON / XOFF: para fazer isso, execute stty -ixon.)

Isso está documentado em "Pesquisando" em man bash.

John1024
fonte
11
Ctrl-Qpara sair do estado congelado, se você já tiver batido Ctrl-Ssem desligar o controle de fluxo primeiro e tiver congelado o terminal.
HongboZhu 24/01
26

Coloque estes em seu ~/.inputrc:

"\e[5~": history-search-backward
"\e[6~": history-search-forward

Estes fazem Page Upe Page Downse comportam como você deseja. (Algumas distribuições já o configuraram para você.) Pessoalmente, acho isso mais conveniente do que Ctrl+ Rou history.

Egmont
fonte
Essa é a maneira mais conveniente em todas as respostas atuais. Você poderia dar uma pequena explicação sobre o mecanismo de trabalho?
Lee
3
~/.inputrcou /etc/inputrcou o arquivo referenciado pela variável de ambiente $INPUTRCé o arquivo de configuração de edição de linha de todos os aplicativos usando o readline, incluindo o bash (seu shell). Ele possui alguns recursos internos de edição de linha, incluindo os dois: na página de manual do bash, procure por uma dessas palavras-chave para descobrir mais. \e[5~/ \e[6~são as seqüências de escape geradas pelas teclas Page Up / Down na maioria dos emuladores de terminal; para vê-lo, inicie o catcomando e pressione essas teclas (o byte de escape é representado no terminal como ^[, em inputrc como \e).
egmont 24/09
O exemplo na sua pergunta original diz que as teclas Para cima / Para baixo funcionam dessa maneira no Matlab. Seria interessante ver o que aconteceu se você colocasse a sequência de Acima e Abaixo em inputrc e atribuísse a esta ação; funcionaria corretamente ou teria efeitos colaterais desagradáveis, pois entra em conflito com o comportamento padrão. Não sei, ficaria feliz em ouvir suas descobertas se você experimentar isso.
egmont
Quando eu faço echo $INPUTRCisso está vazio. Estou usando o Ubuntu 14.04
JorgeeFG
2
Pessoalmente, prefiro substituir a seta para cima e para baixo para fazer isso: "\e[A": history-search-backwarde"\e[B": history-search-forward
A.Wan
9

Além da história da ^ r / ^ s, i-search:

alt.insere a última "palavra" do comando anterior no cursor. Repita para obter a última palavra dos comandos mais antigos. (Mas observe que um final &conta como a última palavra para comandos em segundo plano).

Isso é super útil para mkdir foo, cdalt-ponto. Ainda mais rápido que a seta para cima, ^ a, alt-d (excluir palavra para frente) cd,.

Para obter a penúltima palavra, use esc - 2 alt+.(por exemplo, use um argumento numérico no estilo emacs para alt+.. Contagens negativas a partir do final, contagens positivas a partir do início.) Mas isso geralmente é mais problemático do que vale a pena; em algum momento, é mais rápido acessar o mouse e copiar / colar ou seta para cima e ^ w / ^ y parte dele (veja abaixo).


Se o seu terminal estiver configurado de maneira adequada / correta, as teclas Ctrl-Esquerda e Ctrl-Direita retrocederão / avançarão. Se não, espero que pelo menos alt-be alt-f façam a mesma coisa.


ctrl- / é um desfazer. Você pode usar a repetição automática para excluir palavras com muito mais eficiência, se puder desfazer quando exceder um pouco.


A mistura / combinação de comandos mais poderosa vem do uso do kill-ring, que funciona exatamente como no Emacs. ctrl-y para colar o último ctrl-w / ctrl-u / ctrl-backspace / alt-d. Alt-y para percorrer o texto morto mais antigo.

Ctrl-w múltiplo ou o que for seguido em seguida na entrada do anel de interrupção. Use as setas esquerda e direita ou algo para interromper a entrada se desejar remover duas coisas e colar apenas uma depois.

Combinando tudo isso, você pode

  • comece a digitar um comando
  • ctrl-r para retornar a um comando antigo e pegar parte dele com control-w ou similar.
  • esc-r ou alt+rpara restaurá-lo como estava antes de excluir parte dele.
  • alt- >para ir até o fim da história (ou seja, seta para baixo até o fim), voltar ao comando em que você estava no meio.

Outras dicas de uso interativo:

Ative shopt -s globstar, para que você possa fazer **/*.c(recursivo, incluindo o diretório atual). Às vezes, útil para uso interativo, mas geralmente find -name '*.c' -exec foo {} +é melhor.

Se você escrever scripts bash, também será útil ter shopt -s extglobativado seus shells interativos. Você vai , por vezes, encontrar um uso para o material como *.!(c|h)para coincidir com arquivos que não terminam com .c ou .h.

Encontrar aliases que você gosta de ls -l, lesse qualquer outra coisa que você faz um monte. ( cp -i,, mv -ie rm -Isão legais. Não use o hábito de depender deles para fazer uma empresa seletiva. GNU rm's -I pede uma vez todos os argumentos.)

Eu gosto alias m=less(m para "mais"). Eu lessconfigurei ,e .vinculei ao arquivo anterior / seguinte ( lesskey). O padrão é uma sequência de pressionamento de teclas múltiplas que não pode ser usada com repetição automática.


Eu gosto de fazer tudo dentro da tela GNU. Acho mais fácil acompanhar as janelas de tela numeradas do que um monte de guias no Konsole (ou qualquer outro emulador de terminal que eu tentei). Se você ainda não sabe screen, aprenda o tmux porque é mais novo e menos sujo.

Para obter algo parecido com a funcionalidade de abrir um novo shell com o mesmo cwd que outro shell, eu uso um gancho personalizado para cd / pushd / popd que me permite fazer o cds 8cd para qualquer dir que meu shell na janela 8 da tela estiver usando. Isso funciona mesmo para shells fora da sessão de tela, desde que haja apenas uma sessão de tela.

Peter Cordes
fonte
O meu não parece estar "configurado corretamente". Muitos dos atalhos que vejo aqui não funcionam, estou usando o Terminal de estoque do Ubuntu 14.04. Como posso configurá-lo?
JorgeeFG 24/09
@JorgeeFG: Acho que funcionou para mim imediatamente gnome-terminalno Ubuntu 14.04, antes de mudar para o KDE. A opção relevante está nas configurações do seu terminal, esc-prefix vs high-bit, e talvez em outras configurações. Alguns deles não funcionam perfeitamente para mim através do ssh. (por exemplo, ctrl esquerda / direita munge o código de escape para a seta, e eu fico 5Daparecendo literalmente)
Peter Cordes
7

Adicione as seguintes linhas ao seu ~/.inputrc

"\e[A": history-search-backward
"\e[B": history-search-forward

Isso é semelhante à resposta do egmont, mas em vez de usar Page Up e Page Down, ele usa as seqüências de escape para Seta para cima e Seta para baixo. Dessa forma, é muito mais conveniente usar em um Mac.

John Slavick
fonte
4

Eu sempre tendem a configurar minhas máquinas com um grande valor HISTSIZE, para manter uma lista de histórico mais longa, além de HISTTIMEFORMAT com o valor do carimbo de data / hora para que eu possa ver quando o comando foi executado.

export HISTSIZE=10000
export HISTTIMEFORMAT="%m/%d/%Y %T "
Alpha01
fonte
3

O meio que eu costumo usar é combinar o historycomando comgrep

IE:

history | grep <command im looking for>

Isso exibirá um histórico numerado de comandos digitados que contêm esse comando, e você poderá usar:

!<number listed in history command>

refazer esse comando.

IE:

history | grep history

142  history
143  history | grep lvresize
568  history | grep echo
570  history | grep echo
571  history | grep history

Seguido por: !571

vai repetir history | grep history

Molho
fonte
11
CR = muito melhor + muito mais seguro
PSkocik 23/09/2015
11
Talvez, pessoalmente, encontre um histórico direcionado para grep como um meio mais rápido de encontrar a maioria dos comandos. Quanto mais seguro, não tenho certeza do que você quer dizer, quais são os riscos inerentes ao uso do histórico, em vez de pesquisar no cR?
Molho
2
@ Gravy Eu suspeito que PSkocik significa que a !substituição do histórico é menos segura.
Derbert # 23/15
3
@ Gravrav Os riscos inerentes estariam acidentalmente na linha errada. Não faço ideia por que seu terminal congelou, a menos que você tenha usado o Control-S e o controle de fluxo xon / xoff esteja ativado (geralmente o padrão). Nesse caso, o Control-Q o trará de volta.
Derobert 23/09/2015
11
Concordo com o @PSkocik, cr é muito melhor porque é mais fácil editar a linha do histórico, em vez de executá-la novamente da mesma maneira. A execução exata do mesmo comando novamente é um caso trivial do que você pode fazer para economizar tempo redigitando variações em linhas únicas complexas ou preenchendo tabs um arquivo diferente em um longo caminho. Veja minha resposta.
Peter Cordes
1

Usei diariamente 4 dicas (e algumas outras) no meu terminal bash:

  • Execute o último comando: !!

  • Execute o comando N do histórico: !N

  • Imprima o último comando começando com o prefixo do histórico: !prefix:p

  • Execute o último comando começando com o prefixo do histórico: !prefix

Nolwennig
fonte
1

Se estiver tudo bem para você usar em zshvez de bashusar, use oh-my-zsh para isso.

Ele contém a seta para cima e para baixo na navegação pelo histórico de comandos. Permite também a mesma navegação quando você já digitou o texto (como Mathlab).

editar: ele também contém outros itens focados no desenvolvedor, como aliases e temas. Esses extras tornam a distribuição maior e mais complexa de usar.

https://github.com/robbyrussell/oh-my-zsh

user9869932
fonte
11
oh-my-zshcontém toneladas de coisas. Você também pode dizer: Esse recurso exato está incluído nessa distribuição, quando tudo o que você precisa é de uma configuração ou aplicativo específico.
muru
Editei o post: avisei que ele é maior que um aplicativo simples.
user9869932
1

Adicione o seguinte alias ao ~ / .bashrc

alias h='history | awk '"'"'{$1="";print}'"'"' |sed "s/^ *//" |grep -v "^h " | sort | uniq | grep'

Uso: h firevai me dar uma lista de comandos que contêm fogo . ou h ^firevai me dar uma lista de comandos que começam com fogo .

Isso é útil quando quero visualizar uma série de comandos ao mesmo tempo.

A propósito, '"'"'é feio, mas não consegui encontrar outras maneiras de evitar aspas simples em aspas simples.

Hosi Golden
fonte
fyi - h="history | awk '{\$1=\"\"; print}'deve funcionar. alternativamente, crie uma função e chame isso.
darkheart
obrigado darkheart, mas eu tentei o seu código, não foi encontrado trabalhou no meu ambiente, talvez há algo diferente na minha
Hosi Ouro