¿Cómo edito el comando de shell actual sin ejecutarlo?

13

Parece que hay mucha información sobre cómo editar y ejecutar un comando usando su editor usando "edit-and-execute-command (Cx Ce)", pero lo que me gustaría lograr es tomar el comando de shell actual, aplicar cierto filtrado (usando un script) y luego devuélvalo para solicitar más aprobación / cambios manuales antes de la ejecución. ¿Es esto posible con bash?

Piotr Mazurek
fuente
Esta no es la respuesta correcta a la pregunta, pero intente usar el terminal ZSH en lugar del Bash nativo. Tiene autocompletado, así que no ejecute comandos de inmediato. Personalmente, he probado este escenario específico y siempre me obliga a presionar enter cada vez que hago una edit-and-execute-command.
Praveen Premaratne
1
El acceso directo que funciona para mí es Escape+ V, pero todavía va a ejecutar el comando. En cuanto a la solución, agregaría echoen el frente para ejecutarlo imprimiendo el comando en la consola para su revisión.
kenorb
2
¿Puedes por favor dar un ejemplo concreto? No entiendo "aplicar cierto filtrado (usando un script) y luego devolverlo a prompt".
Kent
3
@PraveenPremaratne: zsh no es una terminal , es shell .
Arkadiusz Drabczyk

Respuestas:

7

Última actualización sobre mi experiencia

La parte 0"+y$dden el siguiente mapeo es realmente algo en lo que debe pensar cuidadosamente y adaptarlo a su gusto / flujo de trabajo / experiencia.

Por ejemplo, con mucha frecuencia me encuentro terminando con varias líneas en el búfer, donde solo quiero ejecutar aquella en la que está el cursor; en este caso puedo usar en 0"+y$dd:%d<CR>lugar de 0"+y$dd.

Y este es solo uno de los escenarios posibles.

Respuesta final para quienes gustan vim

Respuesta original

A menudo necesito hacer lo mismo, y lo hago de la siguiente manera. (Normalmente uso el set -o viin bash, por lo que los puntos 1 y 2 a continuación son diferentes si usa set -o emacsel valor predeterminado; según su pregunta, parece que los puntos 1 y 2 están unificados en Ctrl+ xseguido de Ctrl+ e, que es más difícil de escribir, en mi humilde opinión .)

  1. presione Escapepara estar en modo normal,
  2. presione vpara ingresar al editor para editar el comando,
  3. edito el comando como me gusta,

(Aquí es donde haces la pregunta).

  1. golpeado Escape0"+y$dd:wq,
    • Nota: 0"+y$no simplemente "+yy, ya que este último también copiaría la nueva línea, y esto resultaría en ejecutar el comando al pegarlo en la línea de comando,
  2. pegue el portapapeles en la línea de comando
    • cómo hacerlo depende del terminal que estés usando, supongo; Golpeé Ctrl+ Alt+ ven URxvt.
  3. proceder a la aprobación / edición manual.

Claramente, esto es solo una solución, que consiste en copiar el comando editado en el portapapeles antes de eliminar todo el comando, para que nada se ejecute al salir del editor; Sin embargo, es lo mejor que puedo obtener por mí mismo.

Actualizar

Como mi EDITOR(y VISUAL) es igual a vim, cuando edito el comando, lo edito en vim.

A este respecto, he notado que el búfer se llama /tmp/bash-fc.random, donde randomhay una cadena aleatoria alfanumérica de 6 caracteres.

Esto le da espacio a muchas posibilidades, si las usa vimcomo su editor, ya que puede definir algún mapeo en su .vimrcpara ejecutar toda la secuencia Escape0"+y$dd:wq. Por ejemplo, un comando que rara vez usaría al editar una línea de comando es Leaderd; por lo tanto, puede poner el siguiente mapping en su .vimrcarchivo

au BufEnter /tmp/bash-fc.* nn <Leader>d 0"+y$dd:wq<CR>

para que el paso 4 de la receta anterior se convierta

  1. golpear EscapeLeaderd
Enrico Maria De Angelis
fuente
Para mí, esta es la mejor manera de editar comandos
A.Villegas
2

No es posible hacer eso en Bash / readline pero es posible en zsh usando el edit-command-linecomando:

darkstar% autoload edit-command-line; zle -N edit-command-line
darkstar% bindkey "^X^E" edit-command-line

Ahora pulse Control- x Control- epara abrir su editor, editar línea, deje el editor - verá la línea de comandos actualizada pero no se ejecutará automáticamente.

Arkadiusz Drabczyk
fuente
1

Ahora que lo pienso, tal vez una variación de lo que @kenorb sugirió en un comentario es la mejor solución (ya que parece que no existe una solución), si queremos seguir bash.

Lo que puede hacer es anteponer un #(el carácter de comentario en bash) al comando, en lugar de echo. Luego, cuando salga del exitor, el comando será ineficaz y solo tendrá que presionar arrow up(o k, si lo usa set -o vi), eliminar #y confirmar.

Tenga en cuenta que esta estrategia agrega solo unas pocas teclas, por lo que puede ser bastante eficiente, dependiendo de su nivel de escritura.

Enrico Maria De Angelis
fuente
1

Estas piezas pueden acercarte:

a) reemplace el enlace normal para newline newline (ctrl-M) bind -x '"\C-M":date"

b) tome la línea actual del historial usando !#

reemplace fecha con cualquier script que desee.

c) editar manualmente

d) si es necesario, empate de alguna manera el !!:pque imprime el nuevo comando en la línea de comando pero no lo ejecuta, lo que le permite editarlo manualmente.

e) usando ctrl-J enviar comando editado en lugar de una nueva línea

o tal vez no ...

ShpielMeister
fuente
1

Hay una opción en bash para modificar el comando del historial sin ejecutarlo. No estoy seguro de que sea posible usar script para esto, no parece probable. Sin embargo, puede realizar modificaciones utilizando modificadores de historial.

  1. Habilite la opción histverify para evitar la ejecución del comando modificado
  2. Use la cadena de modificadores para cambiar el último comando
  3. Utilizar "!!" para poner su resultado en la línea de comando para la edición final

Así es como se ve:

$ shopt -s histverify
$ ls *.sh
script1.sh  script2.sh  script3.sh  script-return.sh
$ !!:s/*/script1/:p
ls script1.sh
$ !!:s/1/2/:p
ls script2.sh
$ !!
$ ls script2.sh
script2.sh
Maxim Norin
fuente
1

Me gustaría señalarle el marco Composure para Bash (no estoy afiliado a él): https://github.com/erichs/composure

Proporciona drafty revisefunciones que parecen que podrían ayudar con lo que está tratando de hacer. Aquí hay una cita (larga) del archivo Léame del proyecto:

Composure ayuda al permitirle redactar rápidamente funciones de shell simples, desglosando sus filtros de tubería largos y comandos complejos en fragmentos legibles y reutilizables.

Redacta primero, haz preguntas después

Una vez que hayas creado tu gema de comando, ¡no la tires! Usa draft ()y dale un buen nombre. Esto almacena su último comando como una función que puede reutilizar más tarde. Piense en ello como un borrador.

  $ cat servers.txt
  bashful: up
  doc: down

  up-arrow

  $ cat servers.txt | grep down
  doc: down

  $ draft finddown

  $ finddown | mail -s "down server(s)" admin@here.com

Revisar, revisar, revisar!

Ahora que tiene una función de shell mínima, es posible que desee mejorarla mediante la refactorización y la revisión. Use el revise ()comando para revisar su función de shell en su editor favorito.

  • generalizar funciones con parámetros de entrada
  • agregar o quitar funcionalidad
  • agregar metadatos de soporte para la documentación

    $ revise finddown
    finddown ()
    {
      about finds servers marked 'down' in text file
      group admin
      cat $1 | grep down
    }
    
    $ finddown servers.txt
    doc: down
nwinkler
fuente
0

No parece posible con un atajo de teclado, al menos:

$ bind -P | grep -e command -e edit
complete-command can be found on "\e!".
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
possible-command-completions can be found on "\C-x!".
vi-editing-mode is not bound to any keys
l0b0
fuente