Je to možné v interaktivní bash shell pro zadání příkazu, který vypíše nějaký text, takže se objeví na dalším příkazovém řádku, jako by uživatel zadal tento text na tomto řádku ?
Chci umět source
skript, který vygeneruje příkazový řádek a vydá jej tak, aby se zobrazil, když se výzva vrátí po skončení skriptu, takže jej uživatel může volitelně upravit před stisknutím enter
k provedení.
Toho lze dosáhnout pomocí xdotool
ale to funguje pouze tehdy, když je terminál v okně X a pouze pokud je nainstalován.
[[email protected]] 100 $ xdotool type "ls -l"
[[email protected]] 101 $ ls -l <--- cursor appears here!
Lze to provést pouze pomocí bash?
Přijatá odpověď:
Pomocí zsh
, můžete použít print -z
k umístění nějakého textu do vyrovnávací paměti řádkového editoru pro další výzvu:
print -z echo test
by naplnil editor řádků pomocí echo test
kterou můžete upravit na další výzvu.
Nemyslím si, že bash
má podobnou funkci, ale na mnoha systémech můžete naplnit vstupní vyrovnávací paměť koncového zařízení pomocí TIOCSTI
ioctl()
:
perl -e 'require "sys/ioctl.ph"; ioctl(STDIN, &TIOCSTI, $_)
for split "", join " ", @ARGV' echo test
Vloží echo test
do vstupní vyrovnávací paměti koncového zařízení, jako by byla přijata z terminálu.
Přenosnější varianta Terminology
@mike přístup, který neobětuje zabezpečení, by bylo poslat emulátoru terminálu poměrně standardní query status report
escape sekvence:<ESC>[5n
které terminály vždy odpovídají (tedy jako vstup) jako <ESC>[0n
a připojte jej k řetězci, který chcete vložit:
bind '"e[0n": "echo test"'; printf 'e[5n'
Pokud je na screen
GNU , můžete také:
screen -X stuff 'echo test'
Nyní, s výjimkou přístupu TIOCSTI ioctl, žádáme emulátor terminálu, aby nám poslal nějaký řetězec jako napsaný. Pokud se tento řetězec nachází před readline
(bash
's line editor) zakázal místní odezvu terminálu, pak se tento řetězec zobrazí ne při výzvě shellu, což mírně naruší displej.
Chcete-li to obejít, můžete odeslání požadavku na terminál mírně zpozdit, abyste se ujistili, že odpověď dorazí, když bude odezva zakázána pomocí readline.
bind '"e[0n": "echo test"'; ((sleep 0.05; printf 'e[5n') &)
(zde za předpokladu, že máte sleep
podporuje subsekundové rozlišení).
V ideálním případě byste chtěli udělat něco jako:
bind '"e[0n": "echo test"'
stty -echo
printf 'e[5n'
wait-until-the-response-arrives
stty echo
Nicméně bash
(na rozdíl od zsh
) nemá podporu pro takové wait-until-the-response-arrives
který nečte odpověď.
Má však has-the-response-arrived-yet
funkce s 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"
Další čtení
Podívejte se na odpověď @starfry, která rozšiřuje dvě řešení poskytnutá @mikeserv a mnou s několika podrobnějšími informacemi.