GNU/Linux >> Linux Esercitazione >  >> Linux

Bash può scrivere sul proprio flusso di input?

È possibile in una bash interattiva shell per immettere un comando che restituisca del testo in modo che appaia al prompt dei comandi successivo, come se l'utente avesse digitato quel testo in quel prompt?

Voglio essere in grado di source uno script che genererà una riga di comando e la emetterà in modo che appaia quando il prompt ritorna al termine dello script in modo che l'utente possa opzionalmente modificarlo prima di premere enter per eseguirlo.

Questo può essere ottenuto con xdotool ma funziona solo quando il terminale è in una finestra X e solo se è installato.

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

È possibile farlo solo utilizzando bash?

Risposta accettata:

Con zsh , puoi usare print -z per inserire del testo nel buffer dell'editor di riga per il prompt successivo:

print -z echo test

adescare l'editor di riga con echo test che puoi modificare alla richiesta successiva.

Non credo bash ha una caratteristica simile, tuttavia su molti sistemi è possibile adescare il buffer di input del dispositivo terminale con il TIOCSTI ioctl() :

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

Inserisce echo test nel buffer di input del dispositivo terminale, come se fosse ricevuto dal terminale.

Una variazione più portabile della Terminology di @mike approccio e ciò non sacrifica la sicurezza sarebbe inviare all'emulatore di terminale un query status report abbastanza standard sequenza di escape:<ESC>[5n quali terminali rispondono invariabilmente (quindi come input) come <ESC>[0n e associalo alla stringa che vuoi inserire:

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

Se all'interno dello screen di GNU , puoi anche fare:

screen -X stuff 'echo test'

Ora, ad eccezione dell'approccio ioctl TIOCSTI, chiediamo all'emulatore di terminale di inviarci una stringa come se fosse digitata. Se quella stringa viene prima di readline (bash 's line editor) ha disabilitato l'eco locale del terminale, quindi quella stringa verrà visualizzata non al prompt della shell, incasinando leggermente il display.

Per ovviare a questo problema, puoi ritardare leggermente l'invio della richiesta al terminale per assicurarti che la risposta arrivi quando l'eco è stato disabilitato da readline.

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

(qui assumendo il tuo sleep supporta una risoluzione inferiore al secondo).

Correlati:barra e barra rovesciata in sed?

Idealmente vorresti fare qualcosa come:

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

Tuttavia bash (contrariamente a zsh ) non supporta tale wait-until-the-response-arrives che non legge la risposta.

Tuttavia ha un has-the-response-arrived-yet funzione 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"

Ulteriori letture

Vedi la risposta di @starfry che espande le due soluzioni fornite da @mikeserv e da me con alcune informazioni più dettagliate.


Linux
  1. Uno script Bash può essere agganciato a un file?

  2. Un eseguibile può scoprire il proprio percorso? (Linux)

  3. Nascondi l'immissione della password sul terminale

  4. Bash Shell Script:verifica la presenza di un flag e acquisisci il suo valore

  5. Come posso contare il numero di caratteri in una variabile Bash

Come scrivere uno script Bash con esempi

Bash:Scrivi su file

Bash/sh istruzione 'if else'

Come eseguire nohup e scrivere il suo file pid in una singola istruzione bash

Come posso ottenere l'ultimo numero dalla stringa in bash?

Come posso convertire facilmente entità speciali HTML da un flusso di input standard in Linux?