2

Есть ли способ отобразить стандартный ввод строки оболочки отдельно от стандартного потока вывода? Это кажется очень простым вопросом, но я не заметил, что многие люди спрашивают об этом по какой-то причине

В частности, я пытаюсь избежать слияния входных данных со стандартными выходными (и стандартными ошибками) распечатками. Например, я пытаюсь избежать следующего сценария:

$while true; do echo "Hello there. Sorry to barge in; were you busy?"; sleep 1.5; done
Hello there. Sorry to barge in; were you busy?
whaHello there. Sorry to barge in; were you busy?
t Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
stopHello there. Sorry to barge in; were you busy?
 Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
whyHello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?

Вместо этого я хочу что-то похожее на это:

$while true; do echo "Hello there. Sorry to barge in; were you busy?"; sleep 1.5; done
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
>>what
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
>>stop
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
>>why
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
Hello there. Sorry to barge in; were you busy?
>>unsent linefeed content appears fixed over here

Доступна ли эта функция для распространенных реализаций Linux-терминалов? Если нет, то есть ли программа ncurses способная сделать это?

2 ответа2

0

Доступна ли эта функция для распространенных реализаций Linux-терминалов?

Я не думаю, что существует общее решение. Обычные сценарии не очень часто отображают вывод и принимают ввод одновременно - по сути, это поведение многопоточного приложения, и люди обычно собирают в них графические библиотеки вывода, такие как ncurses ...

Если нет, то есть ли программа ncurses, способная сделать это?

Если это так, я никогда не слышал об этом. Вам нужно, чтобы он выполнялся как параллельный процесс с основным сценарием / приложением, а это означает, что вам придется использовать разветвление, нельзя передавать данные в него ... это будет сложно.

Я думаю, что у вас есть только два варианта - либо написать обертку ncurses самостоятельно, либо разделить ее на два терминала. В первом терминале вы запускаете скрипт и принимаете stdin, но stdout и stderr перенаправляются в именованный канал.

$ mkfifo myoutput
$ function blah() { 
>   while true; do 
>     echo "Hello there. Sorry to barge in; were you busy?"; sleep 1.5; 
>   done
> }
$ blah 2>&1 >./myoutput

Теперь вы можете прочитать вывод на другом терминале с помощью cat ./myoutput то время как stdin все еще принимается на исходном терминале.

0

Это может быть сделано, хотя требует, чтобы ваша программа обрабатывала несколько вещей. В частности, программе нужно будет знать все, что набрал пользователь, а это значит, что программе нужно будет перевести терминал в режим raw (отключить ICANON , см. Справочную страницу termios) и обрабатывать отдельные нажатия клавиш по мере их поступления. Затем, когда программе необходимо периодически что-то печатать, она может использовать возврат каретки (или подходящую escape-последовательность для перемещения курсора туда, куда она должна идти, хотя обычно они абстрагируются ncurses), чтобы стереть то, что набрал пользователь; предполагая, что пользователь набрал what но не нажал return, программа выполнит эквивалент sleep и последующей перезаписи echo -e:

 echo -n what; sleep 1; echo -e "\rHello there..."

И тогда вашей программе нужно будет заново отобразить то, что пользователь набрал, но был перезаписан вышеупомянутым; отсюда необходимость работы терминала в режиме raw и буферизации этой информации. В программе оболочки stty может использоваться для установки необработанного режима, а затем некоторые оболочки имеют подходящее read для посимвольного чтения (о, и тогда вам также может понадобиться обрабатывать control+c и другие специальные символы самостоятельно ...)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .