Ist es in einer interaktiven Bash möglich Shell, um einen Befehl einzugeben, der einen Text ausgibt, der an der nächsten Eingabeaufforderung angezeigt wird, als ob der Benutzer diesen Text an dieser Eingabeaufforderung eingegeben hätte ?
Ich möchte source
können ein Skript, das eine Befehlszeile generiert und ausgibt, so dass sie erscheint, wenn die Eingabeaufforderung nach dem Ende des Skripts zurückkehrt, sodass der Benutzer sie optional bearbeiten kann, bevor er enter
drückt um es auszuführen.
Dies kann mit xdotool
erreicht werden aber das funktioniert nur, wenn sich das Terminal in einem X-Fenster befindet und nur, wenn es installiert ist.
[[email protected]] 100 $ xdotool type "ls -l"
[[email protected]] 101 $ ls -l <--- cursor appears here!
Kann das nur mit bash gemacht werden?
Akzeptierte Antwort:
Mit zsh
, können Sie print -z
verwenden um etwas Text in den Puffer des Zeileneditors für die nächste Eingabeaufforderung zu stellen:
print -z echo test
würde den Zeileneditor mit echo test
vorbereiten die Sie an der nächsten Eingabeaufforderung bearbeiten können.
Ich denke nicht bash
hat eine ähnliche Funktion, aber auf vielen Systemen können Sie den Eingangspuffer des Terminalgeräts mit dem TIOCSTI
vorbereiten ioctl()
:
perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
for split "", join " ", @ARGV' echo test
Würde echo test
einfügen in den Eingangspuffer des Terminalgeräts, als ob es vom Terminal empfangen worden wäre.
Eine tragbarere Variante der Terminology
von @mike Ansatz, der die Sicherheit nicht beeinträchtigt, wäre, dem Terminalemulator einen ziemlich standardmäßigen query status report
zu senden Escape-Sequenz:<ESC>[5n
welche Terminals immer antworten (also als Eingabe) als <ESC>[0n
und binden Sie das an die Zeichenfolge, die Sie einfügen möchten:
bind '"e[0n": "echo test"'; printf 'e[5n'
Wenn innerhalb von GNU screen
, können Sie auch Folgendes tun:
screen -X stuff 'echo test'
Mit Ausnahme des IOCSTI-ioctl-Ansatzes bitten wir jetzt den Terminalemulator, uns eine Zeichenfolge zu senden, als ob sie getippt wäre. Wenn dieser String vor readline
kommt (bash
’s line editor) hat das lokale Echo des Terminals deaktiviert, dann wird diese Zeichenfolge nicht angezeigt am Shell-Prompt, was die Anzeige leicht durcheinander bringt.
Um dies zu umgehen, könnten Sie entweder das Senden der Anfrage an das Terminal etwas verzögern, um sicherzustellen, dass die Antwort ankommt, wenn das Echo von readline deaktiviert wurde.
bind '"e[0n": "echo test"'; ((sleep 0.05; printf 'e[5n') &)
(hier unter der Annahme, dass Sie sleep
unterstützt eine Auflösung von weniger als einer Sekunde).
Idealerweise möchten Sie so etwas tun:
bind '"e[0n": "echo test"'
stty -echo
printf 'e[5n'
wait-until-the-response-arrives
stty echo
Allerdings bash
(im Gegensatz zu zsh
) hat keine Unterstützung für ein solches wait-until-the-response-arrives
das die Antwort nicht liest.
Es hat jedoch einen has-the-response-arrived-yet
Funktion mit 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"
Weiterführende Literatur
Sehen Sie sich die Antwort von @starfry an, die die beiden Lösungen von @mikeserv und mir um einige detailliertere Informationen erweitert.