GNU/Linux >> Znalost Linux >  >> Linux

Může Bash zapisovat do svého vlastního vstupního streamu?

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í).

Související:Lomítko a zpětné lomítko v sed?

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.


Linux
  1. Který terminál je lepší:Bash vs Zsh

  2. Může být Bash skript připojen k souboru?

  3. Použití případových prohlášení v Bash

  1. Jak mohu napsat linuxový bash skript, který mi řekne, které počítače jsou v mé LAN zapnuté?

  2. Může spustitelný soubor objevit svou vlastní cestu? (Linux)

  3. Skrýt zadání hesla na terminálu

  1. Bash Shell Script - Zkontrolujte, zda nemáte příznak a zjistěte jeho hodnotu

  2. Jak spustit nohup a napsat jeho soubor pid v jediném příkazu bash

  3. Jaké je použití $# v Bash