GNU/Linux >> Tutoriales Linux >  >> Linux

¿Puede Bash escribir en su propio flujo de entrada?

¿Es posible en un bash interactivo? shell para ingresar un comando que genera un texto para que aparezca en el siguiente símbolo del sistema, como si el usuario hubiera escrito ese texto en ese indicador?

Quiero poder source una secuencia de comandos que generará una línea de comando y la generará para que aparezca cuando vuelva a aparecer la solicitud después de que finalice la secuencia de comandos para que el usuario pueda editarla opcionalmente antes de presionar enter para ejecutarlo.

Esto se puede lograr con xdotool pero eso solo funciona cuando el terminal está en una ventana X y solo si está instalado.

[[email protected]] 100 $ xdotool type "ls -l"
[[email protected]] 101 $ ls -l  <--- cursor appears here!

¿Se puede hacer esto solo con bash?

Respuesta aceptada:

Con zsh , puede usar print -z para colocar algo de texto en el búfer del editor de líneas para el siguiente aviso:

print -z echo test

prepararía el editor de líneas con echo test que puede editar en el siguiente aviso.

No creo que bash tiene una característica similar, sin embargo, en muchos sistemas, puede preparar el búfer de entrada del dispositivo terminal con el TIOCSTI ioctl() :

perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
  for split "", join " ", @ARGV' echo test

Insertaría echo test en el búfer de entrada del dispositivo terminal, como si se hubiera recibido del terminal.

Una variación más portátil de la Terminology de @mike y que no sacrifica la seguridad sería enviar al emulador de terminal un query status report bastante estándar secuencia de escape:<ESC>[5n qué terminales responden invariablemente (como entrada) como <ESC>[0n y vincúlelo a la cadena que desea insertar:

bind '"e[0n": "echo test"'; printf 'e[5n'

Si está dentro de la screen de GNU , también puedes hacer:

screen -X stuff 'echo test'

Ahora, a excepción del enfoque ioctl de TIOCSTI, le estamos pidiendo al emulador de terminal que nos envíe una cadena como si estuviera escrita. Si esa cadena viene antes de readline (bash editor de línea) ha deshabilitado el eco local del terminal, entonces esa cadena se mostrará no en el indicador de shell, estropeando un poco la pantalla.

Para evitarlo, puede retrasar un poco el envío de la solicitud al terminal para asegurarse de que la respuesta llegue cuando readline haya desactivado el eco.

bind '"e[0n": "echo test"'; ((sleep 0.05;  printf 'e[5n') &)

(aquí asumiendo tu sleep admite resolución de subsegundos).

Relacionado:barra oblicua y barra invertida en sed?

Idealmente, querrías hacer algo como:

bind '"e[0n": "echo test"'
stty -echo
printf 'e[5n'
wait-until-the-response-arrives
stty echo

Sin embargo bash (al contrario de zsh ) no tiene soporte para tal wait-until-the-response-arrives que no lee la respuesta.

Sin embargo, tiene un has-the-response-arrived-yet función con read -t0 :

bind '"e[0n": "echo test"'
saved_settings=$(stty -g)
stty -echo -icanon min 1 time 0
printf 'e[5n'
until read -t0; do
  sleep 0.02
done
stty "$saved_settings"

Lecturas adicionales

Vea la respuesta de @starfry que amplía las dos soluciones proporcionadas por @mikeserv y yo con información más detallada.


Linux
  1. Qué terminal es mejor:Bash vs Zsh

  2. Uso de declaraciones de casos en Bash

  3. ¿Cómo puedo escribir un script bash de Linux que me diga qué computadoras están ENCENDIDAS en mi LAN?

  4. Ocultar la entrada del usuario en la terminal en el script de Linux

  5. declaración Bash/sh 'if else'

Cómo escribir un bucle en Bash

Cómo escribir un script Bash con ejemplos

Bash:escribir en archivo

¿Puede un programa leer su propia sección elf?

Cómo ejecutar nohup y escribir su archivo pid en una sola instrucción bash

¿Cómo puedo obtener el último número de una cadena en bash?