Как получить результаты из «\ 033 [6n» в сценарии sh
Мне потребовалось 10 часов поиска в сети и методы тестирования, чтобы получить результаты, которые работали на любой оболочке ( #!/bin/sh
).
В BASH это относительно просто, потому что read
может быть указано, сколько символов нужно схватить, и если обнаружен разделитель, он не будет ждать выхода.
- Что это означает, когда символы появляются в подсказке после операции?
- Сохранение вывода команды в переменную в bash приводит к тому, что «Unescaped left brace in regex устарела»
- Использовать звездочку в переменных
- Подстановки команд vs обратные сбрасывания экранов в цитируемой строке
- Переводчик кода ANSI
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-скрипта, совместимую с любой оболочкой?
- Как правильно избежать этого слова на vim?
- LS_COLORS для 256-цветного терминала
- Как сделать терминал user @ машиной выделен жирным шрифтом?
- Пробел цвет фона при достижении конца терминала
- Апостроф, появляющийся как пространство
- Можно ли использовать коды escape-кода ANSI в Bash здесь-документах?
- Выделите escape-символы Vim, например \ n
- Почему «shift-tab» приводит к «Escape» в терминале?
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
, поскольку оболочка должна быть в интерактивном режиме.
ура
Павел
- Команда работает при копировании и вставке, но не в сценарии bash?
- Почему \ b не заканчивается в конце?