ls
컬러 출력(예: 또는 ) 을 인쇄하는 터미널에서 명령을 실행하면 gcc
컬러 출력이 인쇄됩니다. 내가 이해하는 바에 따르면 프로세스는 실제로 출력됩니다.ANSI 이스케이프 코드, 터미널 서식 색상.
그러나 다른 프로세스(예: 사용자 정의 C 응용 프로그램)를 통해 동일한 명령을 실행하고 출력을 응용 프로그램의 자체 출력으로 리디렉션하면 색상이 유지되지 않습니다.
프로그램은 텍스트를 컬러 형식으로 출력할지 여부를 어떻게 결정합니까? 환경변수가 있나요?
답변1
답변2
환경변수가 있나요?
예. TERM
환경변수 입니다 . 의사결정 과정의 일부로 사용되는 것들이 여러 가지 있기 때문입니다.
모든 프로그램이 단일 결정 흐름도에 동의하는 것은 아니기 때문에 여기에서 일반화하기는 어렵습니다. 실제로 grep
M. Kitt의 답변에 언급된 GNU는 특이한 의사 결정 프로세스를 사용하여 예상치 못한 결과를 생성하는 이상값의 좋은 예입니다. 따라서 일반적으로 다음과 같습니다.
- 표준 출력은 에서 결정한 대로 터미널 장치여야 합니다
isatty()
. - 프로그램은 termcap/terminfo 데이터베이스에서 터미널 유형의 기록을 찾을 수 있어야 합니다.
- 그러므로 반드시 있어야합니다예찾으려는 터미널 유형입니다. 환경
TERM
변수가 존재해야 하며 해당 값은 데이터베이스 레코드와 일치해야 합니다. - 따라서 terminfo/termcap 데이터베이스가 있어야 합니다. 하위 시스템의 일부 구현에서는
TERMCAP
환경 변수를 사용하여 termcap 데이터베이스의 위치를 지정할 수 있습니다. 따라서 일부 구현에는두번째환경 변수. - termcap/terminfo 레코드는 터미널 유형이 색상을 지원함을 선언해야 합니다.
max_colors
terminfo에 필드가 있습니다. 실제로 색상 기능이 없는 터미널 유형에는 설정되지 않았습니다. 실제로 각 색상 지정 가능 터미널 유형에 대해 색상 기능이 없음을 나타내는 또 다른 기록이 있거나 이름에 추가되는 terminfo 규칙이-m
있습니다-mono
. - termcap/terminfo 레코드는 프로그램이 색상을 변경할 수 있는 방법을 제공해야 합니다. terminfo 에는
set_a_foreground
및 필드 가 있습니다.set_a_background
이것은 단지 확인하는 것보다 조금 더 복잡합니다 isatty()
. 그것은 만들어졌다더 멀리몇 가지 사항으로 인해 복잡해졌습니다.
- 일부응용 프로그램은 명령줄 옵션이나 구성 플래그를 추가하여
isatty()
프로그램이 검사를 무시하도록 합니다.언제나또는안 돼요출력으로 (채색 가능한) 터미널이 있다고 가정합니다. 몇 가지 예:- GNU에는 명령줄 옵션이
ls
있습니다 .--color
- BSD는 (부재
ls
는CLICOLOR
안 돼요) 그리고CLICOLOR_FORCE
(그 존재의 의미언제나) 환경 변수이며-G
명령줄 옵션도 지원합니다.
- GNU에는 명령줄 옵션이
- 일부애플리케이션은 termcap/terminfo를 사용하지 않으며 termcap/terminfo 값에 대해 내장된 응답을 갖습니다
TERM
. - 모든 터미널이 ECMA-48 또는 ISO 8613-6 SGR 시퀀스를 사용하는 것은 아닙니다. 이 시퀀스는 "ANSI 이스케이프 시퀀스"로 약간 잘못 명명되어 색상을 변경합니다. termcap/terminfo 메커니즘은 실제로 애플리케이션이 정확한 제어 순서에 대한 직접적인 지식을 얻지 못하도록 설계되었습니다. (게다가 이런 말도 있습니다.아무도ISO 8613-6 SGR 시퀀스를 사용하십시오.모두가 이 실수에 동의한다RGB 색상의 SGR 시퀀스에 대한 구분 기호로 세미콜론을 사용합니다. 표준은 실제로 콜론을 지정합니다. )
앞서 언급했듯이 GNU는 grep
실제로 몇 가지 추가적인 복잡성을 나타냅니다. termcap/terminfo, 내보낼 하드와이어 제어 시퀀스 및 TERM
환경 변수에 대한 하드와이어 응답을 참조하지 않습니다.
이것Linux/Unix 포트에는 다음 코드가 있습니다.TERM
, 환경 변수가 존재하고 해당 값이 하드와이어된 이름과 일치하지 않는 경우에만 색상 지정을 활성화합니다 dumb
.
정수 색상이 지정되어야 합니다(null). { char const *t = getenv("TERM"); return t && strcmp(t, "dumb") != 0; }
따라서 귀하의 프로그램이 이라 할지라도 TERM
GNU xterm-mono
는 grep
다른 프로그램(예를 들어)이 색상을 방출하지 않더라도 색상을 방출하기로 결정합니다 vim
.
이것Win32 포트에는 다음 코드가 있습니다.TERM
, 이는 환경 변수 에 색상을 지정하여 달성할 수 있습니다.확실히존재하거나 존재하고 해당 값이 하드와이어된 이름과 일치하지 않는 경우 dumb
:
정수 색상이 지정되어야 합니다(null). { char const *t = getenv("TERM"); 반품! (t && strcmp(t, "dumb") == 0); }
GNU grep
색상 문제
GNU grep
의 색상화는 실제로 악명 높습니다. 실제로 터미널 출력을 올바르게 작성하지 않고 이것이 충분할 것이라는 헛된 희망으로 출력의 다양한 지점에서 일부 하드와이어 제어 시퀀스를 비난하기 때문에 실제로 일부 경우 출력이 잘못 표시됩니다.
이 경우 터미널 오른쪽 가장자리에 색상을 지정해야 합니다. 터미널 출력을 올바르게 수행하는 프로그램은 자동 오른쪽 여백을 고려해야 합니다. 또한터미널에 해당 필드(즉, terminfo의 필드)가 없을 가능성이 적습니다 auto_right_margin
. 자동 오른쪽 여백이 있는 터미널의 동작은 일반적으로 DEC VT 선례를 따릅니다.개행 대기 중. GNU는 grep
이것을 고려하지 않았고 순진하게 예상했습니다.즉시 줄 바꿈, 색상 출력이 잘못되었습니다.
컬러 출력은 단순한 문제가 아닙니다.
추가 읽기
- 디키, 토마스 E. (2016). "
grep --color
올바른 출력이 표시되지 않음".xterm FAQ. 보이지 않는 섬. - 조나단 데보인 폴라드(2016).nosh 사용자 공간 가상 터미널 맨 페이지의 기울임꼴 및 색상. 스낵팩.
답변3
이 unbuffer
명령은 다음에서 비롯됩니다.예상되는패키지는 첫 번째 프로그램의 출력과 두 번째 프로그램의 입력을 분리합니다.
다음과 같이 사용할 수 있습니다.
unbuffer myshellscript.sh | grep value
나는 ansible과 homebrew와 함께 사용하고 있습니다.입방체로그 파일을 일반(비컬러) 출력으로 남겨두고 터미널에서 컬러 출력을 볼 수 있도록 스크립트합니다.
unbuffer ansible-playbook myplaybook.yml | ctee /var/log/ansible/run-$( date "+%F" ).log