Строки и столбцы переменные среды, потерянные в скрипте



рассмотрим следующее:



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 линии, конечно, не идеальное решение, но по крайней мере лучше, чем потерять предыдущий экран)

731   11  

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 example 

The 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

Баш DEBUG trap выполняется перед каждой командой, введенной в командной строке, поэтому мы можем использовать ее для экспорта этих переменных. При повторном экспорте их с каждой командой мы гарантируем, что переменные среды остаются актуальными, если изменяется размер терминала. Добавьте эту строку .bashrc вместе с показано выше. Он отлично работает для личного скрипты, но я не рекомендую использовать эти переменные в любом скрипте, который будет общим.

eval $( resize )

делает эту работу...(на xterm-терминале)

kill -s WINCH $$

устанавливает переменные.

вы пробовали сделать ваш shebang сказать:

#!/bin/bash -i

под управлением 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 и $COLUMNS in 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

    Ничего не найдено.