printf의 "%*s" 패딩 형식에 영향을 주지 않고 터미널에서 글꼴 색상을 변경할 수 있습니까?

printf의 "%*s" 패딩 형식에 영향을 주지 않고 터미널에서 글꼴 색상을 변경할 수 있습니까?

message_offsetbash 스크립트의 상태를 인쇄하는 bash 스크립트 기능이 있습니다 .
즉, 아래와 같이 메시지와 상태를 전달하여 호출할 수 있습니다.

message_offset "install font library" "[   OK   ]" 

항상 80열 너비의 가장 오른쪽 문자를 설정하는 데 사용되는 형식 printf으로 터미널에 인쇄됩니다. 예를 들어 출력은 다음과 같습니다.%*s[ OK ]

install font library                              [   OK   ]
update configuration file on server               [   ERR  ]
                                                           ^
                                                           |
                                                      always
                                                        at 80

다음을 사용 하면 echo출력은 다음과 같습니다.

install font library                 [   OK   ]
update configuration file on server               [   ERR  ]

암호:

#!/usr/bin/env bash

function message_offset() {

    local message="$1"
    local status="$2"

    # compensate for the message length by reducing the offset 
    # by the length of the message, 
    (( offset = 80 - ${#message} ))

    # add a $(tput sgr0) to the end to "exit attributes" whether a color was
    # set or not
    printf "%s%*s%s" "${message}" 80 "$status" "$(tput sgr0)"

}

tput를 사용하여 문자열에 일부 색상 시퀀스를 추가하려고 시도하기 전까지는 이 모든 것이 잘 작동합니다. 이로 인해 "[ERR]"이 빨간색으로 변합니다. 포맷팅은 오프셋을 설정할 때 tput 문자 순서를 계산하는
것 같으니 printf "%*s"이렇게 함수를 호출하면

message_offset "update configuration file on server"  "$(tput setaf 1)[   ERR  ]"

출력은 다음과 유사합니다.

install font library                              [   OK   ]
update configuration file on server          [   ERR  ]

이 문자열에는 모든 문자와 문자가 printf "%*s"포함되어 있지만 분명히 문자가 인쇄되지 않으므로 실제로 패딩 에 영향을 미치지 않습니다. "상태" 메시지에 색상을 추가하고 스타일 색상 순서를 사용할 수 있는 방법이 있습니까 ?"[ ERR ]""$(tput setaf 1)"$(tput setaf 1)
tput

답변1

필요한 것보다 훨씬 더 복잡하게 만들고 있습니다. $messageANSI 시퀀스의 너비를 고려하지 않고 정렬을 처리할 수 있습니다 .

#! /usr/bin/env bash

message() {
    [ x"$2" = xOK ] && color=2 || color=1
    let offset=$(tput cols)-4-${#2}
    printf "%-*s[ %s%s%s ]\n" $offset "$1" "$(tput setaf "$color")"  "$2" "$(tput sgr0)"
}  

message "install font library" "OK"
message "update configuration file on server" "ERR"

편집하다:대부분의 printf(1)구현에서는 멀티바이트 문자 집합에 대한 길이 계산을 제대로 처리하지 못합니다. 따라서 UTF-8 형식의 악센트 문자가 포함된 메시지를 인쇄하려면 다른 접근 방식을 취해야 할 수도 있습니다.어깨를 으쓱하다

답변2

쉬운 방법은 모든 것을 색칠하는 것입니다뒤쪽에이미 정렬됐어

간단히 말해서, 당신은 필요합니다

  • 문자열을 색상으로 색칠하는 함수(또는 더 나은 외부 스크립트)(예: Perl의s,$regex,$color$&$resetcolor,gi

  • 당신은 그것을 호출뒤쪽에인쇄하셨습니다. 색상 이스케이프 코드는 이러한 방식으로 정렬을 변경하지 않습니다.

예를 들어, 색상 매개변수를 사용하고 그 뒤에 해당 색상으로 색상을 지정하려는 정규식을 사용하는 "colorize"라는 스크립트를 생성한다고 가정해 보겠습니다. 예를 들어 colorize -blue 'regex1' -green 'regex2' 필요할 때 호출합니다.

 { code
   that
  formats and display things
 } | colorize -red 'ERR' -green 'OK'

스크립트 자체로 사용하면 어디에서나 사용할 수 있습니다. 예를 들면 다음과 같습니다.

 df -h | colorize -red '[890].%'

관련 정보