Sé que puedo ejecutar el último comando en bash, con !!
, pero ¿cómo puedo ejecutar la última línea de salida?
Estoy pensando en el caso de uso de esta salida:
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
Pero no sé cómo puedo ejecutar eso. Estoy pensando en algo así !!
, ¿quizás @@
o similar?
command_not_found_handle
función de shell o un script que ejecuta (generalmente solo/usr/lib/command-not-found
). Creo que podría hacerlo para que se le solicite interactivamente con la opción de instalar automáticamente el paquete, o (probablemente mejor) para que el nombre del paquete se almacene en algún lugar y pueda instalarse ejecutando un comando breve. Eso es lo suficientemente diferente de lo que ha preguntado aquí, puede considerar publicar una pregunta por separado al respecto.Respuestas:
El comando
$(!! |& tail -1)
debe hacer:Como puede ver, el
sudo apt-get install git
comando se está ejecutando.EDITAR: Desglosando
$(!! |& tail -1)
$()
es elbash
patrón de sustitución de comandobash
se expandirá!!
al último comando ejecutado|&
La parte es complicada. Normalmente, la tubería|
tomará el STDOUT del comando del lado izquierdo y lo pasará como STDIN al comando del lado derecho de|
, en su caso, el comando anterior imprime su salida en STDERR como un mensaje de error. Por lo tanto, hacerlo|
no ayudaría, necesitamos pasar tanto STDOUT como STDERR (o solo STDERR) al comando del lado derecho.|&
pasará STDOUT y STDERR tanto como STDIN al comando del lado derecho. Alternativamente, mejor solo puedes pasar el STDERR:tail -1
como de costumbre, imprimirá la última línea desde su entrada. Aquí, en lugar de imprimir la última línea, puede ser más preciso como imprimir la línea que contiene elapt-get install
comando:fuente
TL; DR:
alias @@='$($(fc -ln -1) |& tail -1)'
Las instalaciones de interacción histórica de Bash no ofrecen ningún mecanismo para examinar la salida de los comandos. El shell no almacena eso , y la expansión del historial es específicamente para comandos que usted mismo ha ejecutado o partes de esos comandos.
Esto deja el enfoque de volver a ejecutar el último comando y canalizar tanto stdout como stderr (
|&
) en una sustitución de comando. La respuesta de heemayl logra esto, pero no se puede usar en un alias porque el shell realiza la expansión del historial antes de expandir los alias, y no después.Tampoco puedo hacer que la expansión del historial funcione en una función de shell, incluso habilitándola en la función con
set -H
. Sospecho que!!
una función nunca se expandirá, y no estoy seguro de a qué se expandiría si lo fuera, pero en este momento no estoy seguro de por qué no lo es.Por lo tanto, si desea configurar las cosas para poder hacerlo con muy poca escritura, debe usar el
fc
shell incorporado en lugar de la expansión del historial para extraer el último comando del historial. Esto tiene la ventaja adicional de que funciona incluso cuando la expansión del historial está desactivada.Como se muestra en la respuesta de Gordon Davisson a la creación de un alias que contiene la expansión del historial de bash (en Super User ), simula . El tapar esto en para en comando de heemayl rendimientos:
$(fc -ln -1)
!!
!!
$(!! |& tail -1)
Esto funciona como
$(!! |& tail -1)
pero puede ir en una definición de alias:Después de ejecutar esa definición, o ponerla
.bash_aliases
o.bashrc
iniciar un nuevo shell, simplemente puede escribir@@
(o lo que sea que haya llamado alias) para intentar ejecutar la última línea de salida del último comando.fuente
./script
, no es que la fuente con.
osource
incorporado - Estoy seguro. Bash se agrega a un archivo al salir del shell o cuando se ejecutahistory
con-a
o-w
(verhelp history
). Si lo hiciera, los comandos en múltiples shells interactivos se intercalarían (apareciendo en el orden en que los ejecutó). Puede hacer que se agregue de inmediato. . Pero creo que hay más por hacer parafc
trabajar en un guión. Sugiero publicar una nueva pregunta sobre esto. Si lo hace, no dude en comentar aquí con un enlace.Si está utilizando un emulador de terminal bajo X, como
gnome-terminal
,konsole
oxterm
, puede usar la selección X para algo como copiar y pegar:Usa la selección primaria
Seleccione toda la línea para ejecutar con un triple clic izquierdo .
Luego péguelo en la línea de comando con un clic en el botón central .
Esto debería funcionar en la mayoría de los emuladores de terminal. Utiliza la selección principal, sin tocar el portapapeles, están separados.
Está seleccionando, y luego combina copiar y pegar en una operación, técnicamente.
fuente
Como mencionó Eliah Kagan , el shell no almacena la salida del comando. Sin embargo, hay una manera de obtener la última línea de salida del último comando, sin ejecutar el comando nuevamente , si ejecuta la pantalla .
Pon las siguientes líneas en ti
~/.screenrc
:Luego puede presionar Ctrl+ atpara insertar la línea anterior en el indicador actual. Sería posible hacer que esto también presione automáticamente enter, pero probablemente sea una mejor idea verificarlo antes de ejecutar y simplemente presionar enter manualmente.
Cómo funciona:
register t
registra una cadena en un búfer llamadot
. La cadena que sigue es una secuencia de teclas.bind t
se une a la clave t(es decir, ejecutar usando Ctrl+ at),process t
significa evaluar el contenido del buffer nombradot
.^a[
(= Ctrla[): ingrese al modo de copiak
ir una línea hacia arriba,0
ir al principio de la línea,y$
copiar hasta el final de la línea, (espacio) completar el comando^a]
(= Ctrla]): pegar contenido copiado^a^L
(= CtrlaCtrlL) actualice la pantalla (de lo contrario, el contenido pegado no aparecerá, porque no lo escribió usted mismofuente