¿Cómo cambiar rápidamente la primera palabra en un comando Bash?

44

Me gustaría mejorar un poco mi flujo de trabajo con Bash, y me doy cuenta de que a menudo quiero ejecutar el mismo comando en un ejecutable diferente.

Algunos ejemplos:

Git (donde me gustaría cambiar rápidamente la segunda palabra):

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

Cat / rm (donde solo se debe cambiar la primera palabra):

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

Sé que puedo presionar Ctrl+ y aluego Deleliminar la primera palabra, pero me pregunto si hay una manera más rápida de hacerlo.

nowox
fuente
Honestamente, creo que es más seguro usar Ctrl + a y eliminar. Definitivamente no es muy lento.
agosto

Respuestas:

56

!$ se expande a la última palabra de su comando anterior.

Entonces podrías hacer:

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

rm !$

o:

git diff foo/bar.c

git checkout !$

Tus ejemplos solo repetían la última palabra, así que !$funcionó bien. Si realmente tuvieras muchos argumentos que quisieras repetir, y solo quisieras cambiar la primera palabra, podrías usar !*, que se expande a todas las palabras del comando anterior excepto el cero.

Consulte la sección "EXPANSIÓN DE HISTORIA" de la bashpágina del manual. Hay mucha flexibilidad allí.

Spiff
fuente
16
Correcto y correcto. Solo me gustaría poner una advertencia : con !$usted no tiene un control visual completo de la línea que está ejecutando . Esto puede resultar dañino a veces. Especialmente si incurres en un error tipográfico. Toma de historyqué expandirse. Entonces, si escribe el último comando con un espacio en blanco al principio, probablemente este comando no termine en el historial. Cuando ejecute su nuevo comando con !$el shell, no tomará los parámetros de la última línea de comando escrita, sino solo de la última del historial. Aquí las mismas palabras más.
Hastur
1
@Hastur Puede configurar su shell para expandir el historial en la pestaña o al ingresar para evitar accidentes.
slhck
2
@Hastur es por eso que debes presionar la introducción dos veces en zsh (promoción descarada)
Braiam
@Hastur: cuando tengo dudas sobre lo que va a suceder o me doy cuenta tardíamente de que tengo que hacer otra cosa antes de ejecutar algo que acabo de escribir, voy al principio de la línea y agrego una #o una echo para poder lo veo y entra en la historia para que pueda recuperarlo y ejecutarlo nuevamente sin el prefijo de desactivación.
Joe
28

Ctrl+ apara ir al comienzo de la línea, luego Alt+ dpara eliminar la primera palabra.

jjlin
fuente
99
El método abreviado de eliminación de palabras es en realidad Meta + d, y Meta generalmente se asigna a Alt en máquinas Linux. En plataformas donde este no es el caso, una alternativa para obtener el modificador Meta es usar el Escape como prefijo. Ver en.wikipedia.org/wiki/Meta_key
Gustavo Giráldez
2
@ GustavoGiráldez si quieres profundizar, Meta+Dsolo es válido si emacsestá habilitado (a través set -o emacso simplemente por defecto). No funcionará en el modo de editor inferior o si emacsestá deshabilitado.
TC1
En muchas terminales (porque esto es una cosa terminal y no una cosa Bash), la tecla de inicio también irá al comienzo de una línea. Muchas computadoras portátiles asignan Fn + Izquierda a la tecla de inicio. Del mismo modo, la tecla de finalización generalmente irá al final de la línea. Todavía tengo que usar un emulador de terminal que no sea compatible con estas teclas de acceso rápido.
Kat
1
@Mike Por otro lado, C-ay M-des mucho más rápido escribir si sus manos ya están en posición de escritura.
jjlin
@ Mike Esto es una cosa bash. Escriba caty compare lo que obtiene al presionar Inicio ( ^[[Haquí) y al presionar Ctrl + a ( ^A).
Jonas Schäfer
17

No estoy seguro de si realmente sería más rápido o no, pero vea este artículo, particularmente el punto # .3:

  1. Reemplace una cadena del comando anterior usando ^ str1 ^ str2 ^

En el siguiente ejemplo, primero ejecutamos el comando ls para verificar un archivo. Más tarde nos dimos cuenta de que queremos ver el contenido del archivo. En lugar de escribir nuevamente el nombre completo del archivo, podemos reemplazar el "ls" en el comando anterior con "cat" como se muestra a continuación.

$ ls /etc/cron.daily/logrotate

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

Alt+.

Si solo necesita repetir la última parte de uno de los comandos anteriores, puede usar Alt+ .que pegará el último argumento tomado de la última línea del historial.

Si se presiona más de una vez, sustituirá lo que acaba de pegar con el último argumento de la línea anterior ...

Por ejemplo, si los últimos 2 comandos fueron:

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

En el shell escribo rmy presiono Alt+ .aparecerá:

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

si presiono nuevamente Alt+ .aparecerá en su lugar

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

y así...

Hastur
fuente
No estoy seguro de por qué, pero esto no funciona en mi consola Mac.
lulalala
Aquí están los atajos de teclado con los que se sabe que funcionan bash. Por cierto, ¿estás seguro de que estás usando bash como shell ?
Hastur
1
Supongo que esto es una cosa de Mac. Cuando
escribo
12

Además de la respuesta @jjlin, puede que le interesen los siguientes consejos:

  • Ctrl+ welimina la palabra a tu izquierda
  • Ctrl+ kelimina del cursor al final de la línea de comando
  • Ctrl+ uelimina del cursor al inicio de la línea de comando
  • Alt+ bmueve el cursor una palabra hacia atrás
  • Alt+ fmueve el cursor una palabra hacia adelante
  • $_ contiene el último argumento de la línea de comando anterior

Para obtener más información sobre estos, busque la sección "Nombres de comandos de Readline" de la página de bashmanual.

p.ej:

cat foo/is/a/very/long/path/to/bar.c
rm $_
maiki
fuente
Esos son buenos consejos, pero no responden la pregunta.
slhck
@slhck En mi humilde opinión, lo hace porque el título de la pregunta no coincide con los ejemplos dados. Si nos centramos en los ejemplos, como lo hice, el título debería ser "¿Cómo cambiar rápidamente una palabra en un comando bash?" . Esta es también la razón por la cual mi respuesta es "además de la de @jjlin". Pero supongo que la pregunta debería aclararse.
maiki
El OP siempre quiere eliminar (intercambiar) las primeras npalabras en el comando, n = 1en el primer ejemplo y n = 2en el segundo. La respuesta de jjlin muestra cómo eliminar la primera palabra (y al volver a aplicar el acceso directo, eliminar hasta npalabras). Su respuesta enumera algunos atajos de Bash (que de hecho son útiles), pero ninguno de ellos son formas eficientes de eliminar las primeras npalabras.
slhck
Hm, leyendo de nuevo, el $_parámetro probablemente funcionaría si solo hay un argumento (es decir, si n = m - 1dónde mestá el número total de argumentos). Sin embargo, el resto de los atajos es irrelevante para la pregunta.
slhck
@slhck En aras de la discusión, he leído el primer ejemplo como "reemplazar la segunda palabra" :-)
maiki
8

Si eres experto en vi, puedes activar los enlaces de vi en bash (¿la mayoría de los shells?) Usando el comando set -o vi. Luego, puede usar las teclas vi normales para editar su comando. En su primer ejemplo, podría hacer ^wcwpara eliminar "diff", luego cambiarlo a finalizar la compra.

Puede que no valga la pena aprender las combinaciones de teclas vi solo para editar la línea de comando, pero si ya las conoce, es un buen refuerzo de productividad.

Caosed0
fuente
Aprendí en kornshell, ¡así set -o vifue como viví! Incluso hago esto en mis indicaciones de bash también.
bgStack15
bindkey -vpara zsh. Esc 0 c w
user530873
6

¡Hay muchas maneras de pelar a este gato!

Para reemplazar una cadena específica, ^old^new^extrase llevará a su comando anterior, reemplace oldcon new, y anexar extra. Puedes parar tan pronto como quieras; por ejemplo ^old, reemplazará oldcon la cadena vacía y agregará la cadena vacía (esencialmente eliminando oldy no haciendo nada más).

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

Variante especialmente útil de esto:

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

Para reemplazar una palabra específica, puede usar !m:n-ppara referirse a las palabras a ntravés pdel comando m(use números negativos para contar desde el comando actual). Puede omitir la -pparte para referirse a una sola palabra, y omitir la :m-pparte para referirse a un comando completo. Las formas especiales !!para !-1, !$para la última palabra del comando anterior, y !*para los argumentos (todos menos la palabra 0) del comando anterior son bastante útiles.

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

A menudo uso ambos; zsh es especialmente agradable aquí, ya que presionar la pestaña expandirá las cosas crípticas para asegurarte de que lo has hecho bien.

También hay muchas maneras de hacer esto con la edición de línea. Lea sobre las combinaciones de teclas de su shell.

Daniel Wagner
fuente
-2

La mayoría de los programas de terminal admiten ...

  • Presione <Up-Arrow>según sea necesario para volver a mostrar una de las líneas de comando anteriores del historial.
    • Presione <Down-Arrow>según sea necesario para avanzar por la lista del historial.
  • Presione <Left-Arrow>según sea necesario para mover el cursor al final de la segunda palabra.
  • Presione <Backspace>según sea necesario para borrar la segunda palabra.
  • Escriba la segunda palabra de reemplazo.
    • Presione <Right-Arrow>/ <Left-Arrow>según sea necesario para reposicionar para más cambios.
  • Presiona <RETURN>para ejecutar el comando

Si la línea de comando que desea no era reciente, realice una búsqueda inversa <Ctrl-r>como se describe en la pregunta ...
¿Hay alguna forma de usar ctrl-r después de escribir parte del comando en bash?
Luego edite con las teclas de flecha según sea necesario.

DocSalvager
fuente
-3

Lo que hago (Ubuntu / bash):

1) Arrow uphey para regresar el comando anterior
2) Hometecla para regresar al comienzo
3) Modificar el comando según sea necesario.

A prueba de idiotas y especialmente útil para comandos de varias líneas.

Vorac
fuente