LINES 및 COLUMNS 환경 변수가 스크립트에서 손실 됨
다음을 고려하세요:
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쉘 변수입니다 하지 환경 변수, (I 원격 위치에서 ssh를 통해 로그인 한 경우에도 xterm 윈도우 크기를 조정할 때 그러나 그들은 자동으로 업데이트됩니다) 따라서 자식 프로세스에 수출되지 않습니다. 스크립트에 현재 터미널 크기를 알리는 방법이 있습니까?
편집 : 이 문제를 해결하기 위해 이것을 필요로합니다 : vi (뿐만 아니라 vim, less 및 유사한 명령)를 사용할 때마다 화면이 엉망입니다. 터미널을 변경하는 것은 옵션이 아니므로 해결 방법을 찾고 있습니다 ( $LINES줄 아래로 스크롤 하는 것이 완벽한 해결책은 아니지만 적어도 이전 화면을 잃는 것보다 낫습니다)
다음에서 행과 열을 가져올 수 있습니다 tput.
#!/bin/bash
lines=$(tput lines)
columns=$(tput cols)
echo "Lines: " $lines
echo "Columns: " $columns
이 질문은 인기가 많기 때문에 약간의 추가 정보와 함께 새로운 답변을 추가하고 싶습니다.
종종 최신 시스템에서 $COLUMNS및 $LINES변수는 환경 변수 가 아닙니다 . 쉘은 각 명령 이후에 이러한 값을 동적으로 설정하며 일반적으로 비대화 형 스크립트에서 액세스 할 수 없습니다. 일부 프로그램은 이러한 값을 내보낼 때 이러한 값을 존중 하지만이 동작은 표준화되지 않았거나 보편적으로 지원되지 않습니다.
Bash는 다음 을 사용하여 옵션을 활성화 할 때 환경이 아닌 프로세스 범위에서 이러한 변수를 설정합니다 checkwinsize.
shopt -s checkwinsize
많은 시스템에서 기본 또는 시스템 전체 시작 파일 ( / etc / bashrc 또는 이와 유사한) 에서이 옵션을 사용하도록 설정 하므로 이러한 변수를 항상 사용할 수있는 것은 아니라는 점을 기억해야합니다. 같은 Cygwin에서와 같은 일부 시스템에서는이 옵션은 하지 배쉬를 설정하지 않도록, 우리를 활성화 $COLUMNS하고 $LINES우리는 위의 라인을 실행하거나 우리에 추가하지 않는 한 ~ / .bashrc에 .
비 대화식 스크립트를 작성할 때, 우리는 일반적으로에 의존하지 않으려 $LINES하고 $COLUMNS기본적으로 (하지만 우리는 할 수 있습니다 이 원하는 경우 사용자가 수동으로 단말기 크기를 오버라이드 (override) 할 수 있도록 확인).
대신 stty및 tput유틸리티 는 스크립트에서 터미널 크기를 결정할 수있는 휴대용 수단을 제공합니다 (아래에 설명 된 명령은 현재 POSIX에 대한 표준화 중입니다 ).
Puppe 가 받아 들여진 답변 에서 볼 수 있듯이 tput터미널 크기를 매우 간단하게 수집하는 데 사용할 수 있습니다 .
lines=$(tput lines)
columns=$(tput cols)
또는에 대한 size쿼리 stty는 한 단계에서 터미널 행과 열의 수 를 제공합니다 (행 수와 공백 두 개, 열 수로 출력).
size=$(stty size) # "40 80" for example
이 stty프로그램은 일반적으로 GNU Coreutils 와 함께 제공 되므로 tput. 나는 때때로 stty하나의 적은 수의 명령과 서브 쉘 (Cygwin에서는 비싸다)을 호출하기 때문에 접근 방식을 선호 하지만 출력을 행과 열로 구문 분석해야하므로 읽기가 어려울 수 있습니다.
lines=${size% *}
columns=${size#* }
위에서 설명한 두 가지 방법은 모든 POSIX 셸에서 작동합니다. 특히 Bash의 경우 프로세스 대체 를 사용하여 이전 예제를 단순화 할 수 있습니다 .
read lines columns < <(stty size)
... tput예제 보다 빠르게 실행 되지만 stty적어도 내 컴퓨터 에서는 첫 번째 구현 보다 느립니다 . 실제로 성능에 미치는 영향은 미미할 수 있습니다. 프로그램에 가장 적합한 접근 방식을 선택하거나 대상 시스템에서 사용할 수있는 명령을 기반으로합니다.
어떤 이유로 든 스크립트에서 여전히 사용 $LINES하고 싶다면 $COLUMNSBash를 구성하여 이러한 변수를 환경으로 내보낼 수 있습니다.
trap 'export LINES COLUMNS' DEBUG
Bash DEBUG트랩은 프롬프트에 각 명령을 입력하기 전에 실행되므로 이러한 변수를 내보내는 데 사용할 수 있습니다. 각 명령으로 다시 내 보내면 터미널 크기가 변경 될 때 환경 변수가 최신 상태로 유지됩니다. 위에 표시된 옵션 과 함께이 줄을 .bashrc에 추가합니다 checkwinsize. 개인 스크립트에서는 잘 작동하지만 공유 할 스크립트에서는 이러한 변수를 사용하지 않는 것이 좋습니다.
eval $( resize )
그 일을 ... (xterm 기반 터미널에서)
kill -s WINCH $$
변수를 설정합니다.
완료를 위해 'checkwinsize'옵션을 설정하는 것이 OP가 찾고있는 것과 정확히 일치하지만 문제가 있음을 언급하겠습니다. 비대화 형 스크립트에서는 기본적으로 설정되지 않지만 스크립트 시작 부분에 다음 줄을 추가하여 활성화 할 수 있습니다.
shopt -s checkwinsize
Unfortunately, the LINES and COLUMNS variables are not set immediately upon setting the option (at least the last time I tried). Instead, you need to force Bash to wait for a subshell to complete, at which point it will set those variables. The full Bash-only solution to this problem is thus to start your script with the following line :
shopt -s checkwinsize; (:;:)
You can then use the LINES and COLUMNS variables to your heart's content, and they will be reset to the correct values each time the terminal is resized, without needing to call any external utilities.
Have you tried making your shebang say:
#!/bin/bash -i
Running help export might help?
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 and $COLUMNS in bash is just a shell-y wrapper around the TTY ioctls giving you the size of the TTY and the signals sent by the terminal every time that size changes.
You could write a program in some other language which calls those ioctls directly to get to the TTY dimensions, and then use that program.
EDIT: Well, turns out that program already exists, and is called tput. Vote up Puppe's tput based answer.
#!/bin/bash -i
-i works now with 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.
The numbers do change with a window resize; a trap reveals the script is getting a SIGWINCH.
Why not use enviroment variables on exec command like this:
docker exec -ti -e LINES=$LINES -e COLUMNS=$COLUMNS container /bin/bash
My experince that you should start the script by the '. script_to_run' form, instead of the 'scritp_to_run'. A simple check as follows:
'(( ${#COLUMNS} )) || { echo "Try start like '. name'" ; return 1 ; }
'IT Share you' 카테고리의 다른 글
| Rails 애플리케이션의 Javascript Include Tag 모범 사례 (0) | 2020.11.30 |
|---|---|
| Java MessageFormat에서 중괄호를 이스케이프 할 수 있습니까? (0) | 2020.11.30 |
| C ++에서 정적 const 멤버를 초기화하는 방법은 무엇입니까? (0) | 2020.11.30 |
| 리스트를 할 수없는 이유 (0) | 2020.11.30 |
| '지정된 문자열이 제목에 필요한 형식이 아닙니다.'해결 (0) | 2020.11.30 |