Как получить результаты из «\ 033 [6n» в сценарии sh

Мне потребовалось 10 часов поиска в сети и методы тестирования, чтобы получить результаты, которые работали на любой оболочке ( #!/bin/sh ).

В BASH это относительно просто, потому что read может быть указано, сколько символов нужно схватить, и если обнаружен разделитель, он не будет ждать выхода.

 stty -icanon -echo; echo -en "\033[6n"; read -d R -n 12 ESCPOS; stty "$x_TERM"; \ ESCPOS=`echo "$ESCPOS" | tail -c +3`; echo "$ESCPOS" 

Как написать версию sh-скрипта, совместимую с любой оболочкой?

2 Solutions collect form web for “Как получить результаты из «\ 033 [6n» в сценарии sh”

Скопировано с https://unix.stackexchange.com/a/88327

Предполагая, что ваш /bin/sh является POSIX sh (на Solaris 10 и старше, у которых вместо этого была оболочка Bourne, вместо этого используйте /usr/xpg4/bin/sh ):

 if [ -t 0 ] && [ -t 1 ]; then old_settings=$(stty -g) || exit stty -icanon -echo min 0 time 3 || exit printf '\033[6n' pos=$(dd count=1 2> /dev/null) pos=${pos%R*} pos=${pos##*\[} x=${pos##*;} y=${pos%%;*} stty "$old_settings" fi 

Это предполагает, что весь ответ придет в один прием, ожидая его до 0,3 секунды. Это должно быть в целом справедливо для терминальных эмуляторов и устройств pty, но не обязательно для терминалов через последовательный порт. Вы можете изменить его на min 8 time 3 чтобы продолжать ожидание (до 0,3 секунды между каждым байтом), пока не будет прочитано 8 байтов, но с недостатком, что он будет всегда не менее 0,3 секунды, если ответ короче 8 байт и будет вечно вешать, если нет ответа).

Вы можете использовать awk -F'[^0-9]+' -v RS=R '{print $3, $2; exit}' awk -F'[^0-9]+' -v RS=R '{print $3, $2; exit}' с min 1 time 0 . Это будет работать с реализациями awk отличными от mawk (который настаивает на накоплении буфера, заполненного данными на входе, прежде чем начинать его обрабатывать).

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

С SH это сложнее, и мне не удалось найти расширенную версию командной строки встроенного read , в конце концов я нашел упоминание о dd на STDIN, вот результат. Обратите внимание, что версия SH встроенного echo не позволяет использовать echo -en хотя /bin/echo -en работает, мы используем printf вместо этого.

 #!/bin/sh x_TERM=`stty -g` stty -icanon -echo printf "\033[6n" ESCPOS="" X="" I=0 while [ ! "$X" = "R" ]; do X=`dd bs=1 count=1 2>/dev/null` I=`expr $I + 1` if [ $I -gt 2 -a ! "$X" = "R" ]; then ESCPOS="$ESCPOS$X" fi done stty "$x_TERM" #echo "$ESCPOS" CSRLIN=`echo "$ESCPOS" | cut -d \; -s -f 1` POS=`echo "$ESCPOS" | cut -d \; -s -f 2` echo "$CSRLIN" #exit 0 <= dont use inline 

Я использовал один и тот же код в двух разных скриптах, один выводит CSRLIN , другой POS .

EDIT: вам нужно встроить этот скрипт, чтобы использовать его в другом скрипте (например, . CSRLIN , поскольку оболочка должна быть в интерактивном режиме.

ура

Павел

  • Помещение одной цитаты в имя файла
  • Проблема с скриптом с пробелами в имени файла
  • Как определить текущий цвет вывода консоли?
  • Есть ли способ заблокировать название терминала?
  • Вывод ANSI в приглашении Pash отображается как мусор в терминале Gnome
  • Как связать Ctrl + стрелки / backspace / del с командами Readline
  • Как использовать меньше в скрипте без получения ESC escape-символов?
  • Сценарий Bash для создания скрипта со встроенными значениями
  • Значение обратной косой черты
  • Символы запуска оболочки для sh-c
  • Как обратная косая черта динамической строки в bash
  • Linux и Unix - лучшая ОС в мире.