Busque un comando anterior con el prefijo que acabo de escribir

67

Podemos usar las flechas hacia arriba y hacia abajo para navegar en el historial de comandos.

En algunos IDEs, como Matlab, si ingresamos algo y luego presionamos las teclas de flecha, nos desplazamos solo entre los comandos del historial que comienzan con lo que ingresamos. Eso es realmente conveniente, pero en una terminal de shell, esto no funciona.

¿Hay alguna forma de obtener una función similar en un terminal de shell? ¿Y algún otro consejo para mejorar la eficiencia en el uso de terminales?

Sotavento
fuente
Simplemente puede usar un shell que proporcione dicha función, como fish;)
yoann
@yoann estás asumiendo que bash no. Lo hace, a través de readline, simplemente no es accesible por defecto.
muru
@muru Soy consciente de CTRL + R en bash, y la respuesta de egmont proporciona una forma ordenada de hacerlo con Re Pág / Av Pág. Sin embargo, ¿hay alguna manera de hacerlo con las teclas de flecha?
yoann
1
@yoann echa un vistazo a unix.stackexchange.com/a/76591/70524 . En lugar de \e[5~y \e[6~, uso \e[A, \e[B.
muru

Respuestas:

95

Lo que estás buscando es CtrlR.

Escriba CtrlRy luego escriba parte del comando que desee. Bash mostrará el primer comando coincidente. Siga escribiendo CtrlRy bash pasará por los comandos de coincidencia anteriores.

Para buscar hacia atrás en el historial, escriba en su CtrlSlugar. (Si CtrlSno funciona de esa manera para usted, eso probablemente significa que necesita deshabilitar el control de flujo XON / XOFF: para hacerlo, ejecute stty -ixon).

Esto se documenta en "Búsqueda" en man bash.

John1024
fuente
1
Ctrl-Qpara salir del estado congelado, si ya golpeó Ctrl-Ssin apagar primero el control de flujo y congeló su terminal.
HongboZhu
26

Coloque estos en su ~/.inputrc:

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

Estos hacen Page Upy se Page Downcomportan como lo desee. (Algunas distribuciones ya lo tienen configurado para usted.) Personalmente, considero que estas formas son más convenientes que Ctrl+ Ro history.

egmont
fuente
Esta es la forma más conveniente en todas las respuestas actuales. ¿Podría dar una pequeña explicación sobre el mecanismo de trabajo?
Lee
3
~/.inputrco /etc/inputrco el archivo al que hace referencia la variable de entorno $INPUTRCes el archivo de configuración de edición de línea de todas las aplicaciones que utilizan readline, incluido bash (su shell). Tiene ciertas capacidades de edición de línea incorporadas, incluidas estas dos: en la página del manual de bash, busque una de estas palabras clave para obtener más información. \e[5~/ \e[6~son las secuencias de escape generadas por las teclas Page Up / Down en la mayoría de los emuladores de terminal; para verlo, inicie el catcomando y luego presione estas teclas (el byte de escape se representa en la terminal como ^[, en la entrada como \e).
egmont
El ejemplo en su pregunta original dice que las teclas Arriba / Abajo funcionan de esta manera en Matlab. Sería interesante ver qué sucedió si coloca la secuencia de Arriba y Abajo en la computadora y asigna a esta acción; funcionaría correctamente o tendría efectos secundarios desagradables ya que entra en conflicto con su comportamiento predeterminado. No sé, me alegraría escuchar tus hallazgos si experimentas con esto.
egmont
Cuando lo hago echo $INPUTRCestá vacío. Estoy usando Ubuntu 14.04
JorgeeFG
2
Yo personalmente prefiero anulando flecha arriba y abajo para hacer esto: "\e[A": history-search-backwardy"\e[B": history-search-forward
A.Wan
9

Además del historial de ^ r / ^ s i-search:

alt.inserta la última "palabra" del comando anterior en el cursor. Repítalo para obtener la última palabra de comandos más antiguos. (Pero tenga en cuenta que un final &cuenta como la última palabra para los comandos de fondo).

Esto es súper útil para mkdir foo, cdalt-punto. Incluso más rápido que de flecha hacia arriba, ^ a, alt-d (borrar la palabra hacia delante), cd.

Para obtener la penúltima palabra, use esc - 2 alt+.(es decir, use un argumento numérico de estilo emacs para alt+.. El conteo negativo desde el final, el conteo positivo desde el comienzo). Pero esto suele ser más problemático de lo que vale; en algún momento es más rápido alcanzar el mouse y copiar / pegar, o con la flecha hacia arriba y ^ w / ^ y parte de él (ver más abajo).


Si su terminal está configurada bien / correctamente, ctrl-left y ctrl-right irán hacia atrás / adelante por palabras. Si no, con suerte al menos alt-b y alt-f harán lo mismo.


ctrl- / es un deshacer. Puede usar la repetición automática para eliminar palabras de manera mucho más eficiente si puede deshacer cuando se sobrepasa un poco.


La combinación / combinación más potente de comandos proviene del uso del anillo de eliminación, que funciona igual que en Emacs. ctrl-y para pegar el último ctrl-w / ctrl-u / ctrl-backspace / alt-d. alt-y para recorrer el texto eliminado anterior.

Múltiples ctrl-w o lo que sea en una fila hacen en la entrada kill-ring Use la flecha izquierda y derecha o algo para dividir la entrada si desea eliminar dos cosas y solo pegar una más tarde.

Combinando todo esto juntos, puedes

  • comenzar a escribir un comando
  • ctrl-r para volver a un comando anterior y tomar parte de él con control-w o similar.
  • esc-r o alt+rpara restaurarlo a como estaba antes de eliminar parte de él.
  • alt- >para ir al final de la historia (es decir, con la flecha hacia abajo hasta el final), para volver al comando en el que estaba.

Otros consejos de uso interactivo:

Habilite shopt -s globstar, para que pueda hacerlo **/*.c(recursivo, incluido el directorio actual). A veces útil para uso interactivo, pero generalmente find -name '*.c' -exec foo {} +es mejor.

Si escribe scripts de bash, también le resultará útil shopt -s extglobhabilitarlos en sus shells interactivos. A veces encontrarás un uso para cosas como *.!(c|h)hacer coincidir archivos que no terminan con .c o .h.

Encuentra los alias en el que quieres ls -l, lessy cualquier otra cosa que hacer mucho. ( cp -i, mv -iy rm -Ison agradables. No tengas el hábito de depender de ellos para hacer un rm selectivo. GNU rm's -I pregunta una vez por todos los argumentos).

Me gusta alias m=less(m para "más"). He lessconfigurado ,y .vinculado al archivo anterior / siguiente ( lesskey). El valor predeterminado es una secuencia de pulsación de teclas múltiples que no se puede usar con autorepeat.


Me gusta hacer todo dentro de la pantalla GNU. Me resulta más fácil hacer un seguimiento de las ventanas de pantalla numeradas que un montón de pestañas en Konsole (o cualquier otro emulador de terminal que haya probado). Si aún no lo sabe screen, aprenda tmux porque es más nuevo y menos rudo.

Para obtener algo como la funcionalidad de abrir un nuevo shell con el mismo cwd que otro shell, utilizo un enlace personalizado para cd / pushd / popd que me permite hacer cds 8cd a cualquier directorio que esté usando mi shell en la ventana de pantalla 8. Esto funciona incluso para shells fuera de la sesión de pantalla, siempre que solo haya una sesión de pantalla.

Peter Cordes
fuente
El mío no parece estar "configurado correctamente". Muchos de los accesos directos que veo aquí no funcionan, estoy usando el Terminal de Ubuntu 14.04. ¿Cómo puedo configurarlo?
JorgeeFG
@JorgeeFG: Creo que funcionó para mí fuera de la caja gnome-terminalen Ubuntu 14.04, antes de cambiar a KDE. La opción relevante está en la configuración de su terminal, prefijo esc vs bit alto, y tal vez algunas otras configuraciones. Algunos de ellos no funcionan perfectamente para mí a través de ssh. (p. ej., presione Ctrl izquierda / derecha con el código de escape de la tecla de flecha, y 5Daparece literalmente)
Peter Cordes
7

Agregue las siguientes líneas a su ~/.inputrc

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

Esto es similar a la respuesta de egmont, pero en lugar de usar Page Up y Page Down, usa las secuencias de escape para Arrow Up y Arrow Down. De esta manera es mucho más conveniente usarlo en una Mac.

John Slavick
fuente
4

Siempre tiendo a configurar mis máquinas con un valor HISTSIZE grande para que mantenga una lista de historial más larga, así como HISTTIMEFORMAT con el valor de marca de tiempo para que pueda ver cuándo se ejecutó el comando.

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

El medio que suelo usar es combinar el historycomando congrep

ES DECIR:

history | grep <command im looking for>

Eso mostrará un historial numerado de los comandos que ha escrito que contienen ese comando, luego puede usar:

!<number listed in history command>

rehacer ese comando.

ES DECIR:

history | grep history

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

seguido por: !571

repetirá history | grep history

Salsa
fuente
1
CR = mucho mejor + mucho más seguro
PSkocik
1
Quizás, personalmente, encuentro una historia canalizada a grep para ser un medio más rápido de encontrar la mayoría de los comandos. En lo que respecta a Safer, no estoy seguro de lo que quiere decir, ¿cuáles son los riesgos inherentes al usar el historial en lugar de buscarlo con cR?
Salsa
2
@ Gravy Sospecho que PSkocik significa que la !sustitución del historial es menos segura.
derobert
3
@Gravy Los riesgos inherentes serían obtener accidentalmente la línea equivocada. No tengo idea de por qué su terminal se ha congelado, a menos que haya usado Control-S y tenga habilitado el control de flujo xon / xoff (a menudo el predeterminado). Si es así, Control-Q lo traerá de vuelta.
derobert
1
Estoy de acuerdo con @PSkocik, cr es mucho mejor porque es más fácil editar la línea del historial, en lugar de ejecutarla nuevamente de la misma manera. Ejecutar exactamente el mismo comando nuevamente es un caso trivial de lo que puede hacer para ahorrar tiempo al volver a escribir variaciones en líneas complejas o completar con pestañas un archivo diferente en una ruta larga. Mira mi respuesta.
Peter Cordes
1

Usé diariamente 4 consejos (y algunos otros) en mi terminal de bash:

  • Ejecute el último comando: !!

  • Ejecute el comando N del historial: !N

  • Imprima el último comando que comienza con el prefijo del historial: !prefix:p

  • Ejecute el último comando comenzando con el prefijo del historial: !prefix

Nolwennig
fuente
1

Si está bien que lo use en zshlugar de bashusarlo, puede usar oh-my-zsh para eso.

Contiene la flecha hacia arriba y hacia abajo por el historial de comandos. También permite esa misma navegación cuando ya ha escrito texto (como Mathlab).

editar: también contiene otras cosas centradas en el desarrollador, como alias y temas. Que los extras hacen que la distribución sea más grande y más compleja de usar.

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

usuario9869932
fuente
1
oh-my-zshcontiene toneladas de cosas También podría decir: esta característica exacta se incluye en esa distribución, cuando todo lo que necesita es una configuración o aplicación específica.
muru
Edité la publicación: advertí que es más grande que una aplicación simple.
user9869932
1

Agregue el siguiente alias a ~ / .bashrc

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

Uso: h fireme dará una lista de comandos que contienen fuego . o h ^fireme dará una lista de comandos que comiencen con fuego .

Esto es útil cuando quiero ver una serie de comandos al mismo tiempo.

Por cierto, '"'"'es feo, pero no pude encontrar otras formas de evitar comillas simples en comillas simples.

Hosi Golden
fuente
FYI - h="history | awk '{\$1=\"\"; print}'debería funcionar. alternativamente, cree una función y llame a eso.
DarkHeart
gracias DarkHeart, pero probé tu código, encontré que no funcionaba en mi entorno, tal vez hay algo diferente en el mío
Hosi Golden