Less를 사용하여 텍스트 속성을 재설정할 필요가 없는 이유는 무엇입니까?

Less를 사용하여 텍스트 속성을 재설정할 필요가 없는 이유는 무엇입니까?

스크립트는 5줄을 출력하며 세 번째 줄에는 밑줄이 그어져 있습니다.

#!/usr/bin/env bash
set -eu
bold=$(tput bold)
reset=$(tput sgr0)
underline=$(tput smul)
echo 'line 1
line 2
line 3
line 4
line 5' | awk -v bold="$bold" -v reset="$reset" -v underline="$underline" '
    NR == 3 {print underline $0 reset}
    NR != 3 {print $0}
'

(스크립트에서) 세 번째 줄 끝에서 재설정하지 않으면 다음에 입력하는 명령(셸에서)을 포함하여 다음의 모든 줄에 밑줄이 그어집니다. 내가 도망칠 때까지 reset. less( )를 사용하는 것은 (스크립트에서) 불필요할 ./my-script.sh | less -R뿐만 아니라 (세 번째 줄에 밑줄이 그어져 있음) ( , )에 추가 기호가 생성됩니다 .resettmux^OTERM=screen-256color

line 1
line 2
line 3^O
line 4
line 5

하지만 일반 콘솔에는 ( ) 기호가 없습니다 TERM=xterm-256color.

정확히 무엇이고 왜 이런 일이 발생합니까? 이러한 모든 경우에 스크립트가 작동하도록 하는 방법이 있습니까?

$ ./my-script.sh
$ ./my-script.sh | grep line --color=never
$ ./my-script.sh | less -R

예를 들어, 만들기 위해서는다음 스크립트더 잘 일하십시오.

답변1

less줄 끝 부분에 자체 "재설정"을 보냅니다. 이는 sgr0(ncurses)를 통해 terminfo에서 파생되며, termcap 인터페이스가 사용되기 때문에 제거됩니다 ^O. less텀캡 기능terminfo에 해당sgr0대체 문자 세트 상태는 일반적으로 매뉴얼 페이지에 설명된 대로 수정되지 않습니다.curs_termcap(3x):

termcap에는 terminfo와 유사한 것이 없습니다.sgr끈. 이것의 한 가지 결과는 termcap 애플리케이션이 다음을 가정한다는 것입니다.me(용어정보 sgr0)은 대체 문자 세트를 재설정하지 않습니다. 이 구현에서는 이와 관련하여 termcap 제한 사항을 수용하기 위해 termcap 인터페이스에 제공되는 데이터를 검사하고 수정합니다.

아마도 less이것은 예상치 못한 이스케이프 시퀀스를 복구하기 위해 수행될 것입니다. 이 -R옵션은 ANSI 색상(굵게, 밑줄, 깜박임, 강조 표시와 같은 유사한 형식의 이스케이프)만 처리하도록 설계되었습니다. 소스 코드에서는 이에 대해 언급하지 않지만 할당에서는 나중에 재설정을 실행하라고 A_NORMAL지시합니다 .less

    /* 
     * Add a newline if necessary, 
     * and append a '\0' to the end of the line. 
     * We output a newline if we're not at the right edge of the screen, 
     * or if the terminal doesn't auto wrap, 
     * or if this is really the end of the line AND the terminal ignores 
     * a newline at the right edge. 
     * (In the last case we don't want to output a newline if the terminal  
     * doesn't ignore it since that would produce an extra blank line. 
     * But we do want to output a newline if the terminal ignores it in case
     * the next line is blank.  In that case the single newline output for 
     * that blank line would be ignored!) 
     */
    if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON) 
    {
            linebuf[curr] = '\n';
            attr[curr] = AT_NORMAL;
            curr++;
    }

대안으로sgr0(이렇게 하면 재설정됩니다.모두video 속성이며 less에서 부분적으로만 이해됨), 다음을 수행할 수 있습니다.

reset=$(tput rmul)

그리고 (많은 터미널/많은 시스템 포함 TERM=screen-256color) 밑줄만 재설정됩니다. 그러나 이는 영향을 미치지 않습니다.용감한, 그리고 굵은 글씨를 재설정하는 전통적인 terminfo/termcap 기능은 없습니다. 그러나 화면은 해당 ECMA-48 시퀀스(SGR 22와 24에서 사용됨 rmul) 를 구현하므로할 수 있다케이스를 하드코딩합니다.

관련 정보