Строки и столбцы переменные среды, потерянные в скрипте
рассмотрим следующее:
me@mine:~$ cat a.sh
#!/bin/bash
echo "Lines: " $LINES
echo "Columns: " $COLUMNS
me@mine:~$ ./a.sh
Lines:
Columns:
me@mine:~$ echo "Lines: " $LINES
Lines: 52
me@mine:~$ echo "Columns: " $COLUMNS
Columns: 157
me@mine:~$
переменные $LINES и $COLUMNS переменные оболочки, не переменные окружения, и, таким образом, не экспортируются в дочерний процесс (но они автоматически обновляются при изменении размера окна xterm, даже при входе в систему через ssh из удаленного местоположения). Есть ли способ, которым я могу сообщить моему скрипту текущий размер терминала?
изменить:
Мне нужно это как обходной путь сделать проблема: vi (а также vim, less и подобные команды) портит экран каждый раз, когда я его использую. Изменение терминала не является опцией, и поэтому я ищу обходные пути (прокрутка вниз $LINES линии, конечно, не идеальное решение, но по крайней мере лучше, чем потерять предыдущий экран)
11 ответов:
вы можете получить строки и столбцы из
tput:#!/bin/bash lines=$(tput lines) columns=$(tput cols) echo "Lines: " $lines echo "Columns: " $columns
поскольку этот вопрос популярен, я хочу добавить более новый ответ с небольшим количеством дополнительной информации.
часто на современных системах
$COLUMNSи$LINESпеременные не переменные среды. Оболочка устанавливает эти значения динамически после каждой команды, и мы обычно не можем получить к ним доступ из неинтерактивных сценариев. Некоторые программы уважают эти ценности, если мы экспорт их, но это поведение не стандартизировано или универсально поддерживаемый.Bash устанавливает эти переменные в области процесс (не окружающая среда) когда мы включаем использование:
shopt -s checkwinsizeмногие системы включают эту опцию для нас в файле запуска по умолчанию или во всей системе ( / etc / bashrc или аналогичный), поэтому нам нужно помнить, что эти переменные не всегда могут быть доступны. В некоторых системах, таких как Cygwin, этот параметр не включено для нас, поэтому Bash не устанавливается
$COLUMNSи$LINESесли мы не выполним строку выше или не добавим ее в наш ~/.bashrc.
при написании неинтерактивных сценариев мы обычно не хотим полагаться на
на$LINESи$COLUMNSпо умолчанию (но мы можете проверьте их, чтобы позволить пользователю переопределить размер терминала вручную, если это необходимо).sttyиtputутилиты обеспечивают портативный означает определить размер терминала из сценария (ниже описаны команды в настоящее время проходит стандартизация для POSIX).как показано в принятом ответе Puppe, мы можем использовать
tputчтобы собрать размер терминала в довольно простой форме:lines=$(tput lines) columns=$(tput columns)кроме того,
sizeзапросsttyдает нам количество терминальных строк и столбцов за один шаг (выводится как количество строк, за которыми следуют два пробела, за которыми следует количество столбцов):size=$(stty size) # "40 80" for exampleThe
sttyпрограмма обычно поставляется вместе с GNU Coreutils, поэтому мы часто можем найти его в системах безtput. Я иногда предпочитаюsttyподход, потому что мы вызываем на одну команду меньше и подрешетку (дорого на Cygwin), но это требует, чтобы мы разбирали выходные данные на строки и столбцы, которые могут быть менее читаемыми:lines=${size% *} columns=${size#* }оба описанных выше подхода работают в любой оболочке POSIX. Для bash в частности, мы можем использовать подмена процесса для упрощения предыдущего примера:
read lines columns < <(stty size)...который работает быстрее, чем
tputпример, но все же медленнее, чем первыйsttyреализации, по крайней мере на моей машине. На практике влияние производительности, вероятно, незначительно-выберите подход, который лучше всего работает для программы (или на основе которого команда доступна в целевой системе).
если по какой-то причине мы все еще хотим использовать
$LINESи$COLUMNSв наших скриптах мы можем настроить Bash для экспорта этих переменных в среду:trap 'export LINES COLUMNS' DEBUGБаш
DEBUGtrap выполняется перед каждой командой, введенной в командной строке, поэтому мы можем использовать ее для экспорта этих переменных. При повторном экспорте их с каждой командой мы гарантируем, что переменные среды остаются актуальными, если изменяется размер терминала. Добавьте эту строку .bashrc вместе с показано выше. Он отлично работает для личного скрипты, но я не рекомендую использовать эти переменные в любом скрипте, который будет общим.
под управлением
help exportможет помочь?me@mine:~$ cat a.sh #!/bin/bash echo "Lines: " $LINES echo "Columns: " $COLUMNS me@mine:~$ ./a.sh Lines: Columns: me@mine:~$ echo "Lines: " $LINES Lines: 52 me@mine:~$ echo "Columns: " $COLUMNS Columns: 157 me@mine:~$ export LINES COLUMNS me@mine:~$ ./a.sh Lines: 52 Columns: 157 me@mine:~$
$LINESи$COLUMNSin bash-это просто оболочка-оболочка вокруг tty ioctls, дающая вам размер TTY и сигналы, отправляемые терминалом каждый раз, когда этот размер изменяется.вы можете написать программу на каком-то другом языке, который вызывает эти ioctls напрямую, чтобы добраться до измерений TTY, а затем использовать эту программу.
EDIT: Ну, оказывается, что программа уже существует, и называется
tput. Голосуйте за Пуппе,!--2--> на основе ответ.
для завершения позвольте мне упомянуть, что установка опции "checkwinsize" - это именно то, что ищет OP, но есть уловка. Он по умолчанию не установлен в неинтерактивных сценариях, но вы можете добавить следующую строку в начале любого сценария, чтобы включить его:
shopt -s checkwinsizeк сожалению, переменные строки и столбцы не устанавливаются сразу после установки опции (по крайней мере, в последний раз, когда я пытался). Вместо этого Вам нужно заставить Bash ждать subshell для завершения,и в этот момент он установит эти переменные. Полное решение Bash-only для этой проблемы, таким образом, чтобы начать свой скрипт со следующей строки :
shopt -s checkwinsize; (:;:)
#!/bin/bash -i
-iработает с bash 4.2.10(1) - release on Ubuntu 11.10.$ cat show_dimensions.sh #!/bin/bash -i printf "COLUMNS = %d\n" $COLUMNS printf "LINES = %d\n" $LINES $ ./show_dimensions.sh COLUMNS = 150 LINES = 101 $ bash --version GNU bash, version 4.2.10(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.числа меняются с изменением размера окна; ловушка показывает, что скрипт получает SIGWINCH.
почему бы не использовать переменные среды в команде exec следующим образом:
docker exec -ti -e LINES=$LINES -e COLUMNS=$COLUMNS container /bin/bash
мой опыт, что вы должны запустить скрипт '. script_to_run 'форма, вместо 'scritp_to_run'. Простая проверка следующим образом:
'(( ${#COLUMNS} )) || { echo "Try start like '. name'" ; return 1 ; }
Comments