[bash] printf의 패딩 문자

프로세스가 실행 중인지 여부를 표시하는 bash 쉘 스크립트를 작성 중입니다.

지금까지 나는 이것을 얻었다 :

printf "%-50s %s\n" $PROC_NAME [UP]

코드는 다음과 같은 출력을 제공합니다.

JBoss                                              [DOWN]

GlassFish                                          [UP]

verylongprocessname                                [UP]

더 읽기 쉽게 만들기 위해 두 필드 사이의 간격을 ‘-‘또는 ‘*’로 채우고 싶습니다. 필드 정렬을 방해하지 않고 어떻게해야합니까?

내가 원하는 출력은 다음과 같습니다.

JBoss -------------------------------------------  [DOWN]

GlassFish ---------------------------------------  [UP]

verylongprocessname -----------------------------  [UP]



답변

Pure Bash, 외부 유틸리티 없음

이 데모는 완전한 양쪽 맞춤을 수행하지만, 오른쪽의 불규칙한 선을 원하면 두 번째 문자열의 길이를 빼는 것을 생략 할 수 있습니다.

pad=$(printf '%0.1s' "-"{1..60})
padlength=40
string2='bbbbbbb'
for string1 in a aa aaaa aaaaaaaa
do
     printf '%s' "$string1"
     printf '%*.*s' 0 $((padlength - ${#string1} - ${#string2} )) "$pad"
     printf '%s\n' "$string2"
     string2=${string2:1}
done

불행히도이 기술에서 패드 문자열의 길이는 필요하다고 생각하는 가장 긴 길이보다 길도록 하드 코딩되어야하지만, 패드 길이는 표시된대로 변수가 될 수 있습니다. 그러나 패드의 길이에 대한 변수를 사용할 수 있도록 첫 번째 줄을 다음 세 줄로 바꿀 수 있습니다.

padlimit=60
pad=$(printf '%*s' "$padlimit")
pad=${pad// /-}

따라서 패드 ( padlimitpadlength)는 터미널 너비 ( $COLUMNS)를 기반으로 하거나 가장 긴 데이터 문자열의 길이에서 계산 될 수 있습니다 .

산출:

a--------------------------------bbbbbbb
aa--------------------------------bbbbbb
aaaa-------------------------------bbbbb
aaaaaaaa----------------------------bbbb

두 번째 문자열의 길이를 빼지 않고 :

a---------------------------------------bbbbbbb
aa--------------------------------------bbbbbb
aaaa------------------------------------bbbbb
aaaaaaaa--------------------------------bbbb

대신 첫 번째 줄은 동일 할 수 있습니다 (와 유사 sprintf).

printf -v pad '%0.1s' "-"{1..60}

또는 유사하게 더 동적 인 기술 :

printf -v pad '%*s' "$padlimit"

원하는 경우 한 줄에 모두 인쇄 할 수 있습니다.

printf '%s%*.*s%s\n' "$string1" 0 $((padlength - ${#string1} - ${#string2} )) "$pad" "$string2"


답변

퓨어 배쉬. 고정 문자열 ‘line’의 오프셋으로 ‘PROC_NAME’값의 길이를 사용합니다.

line='----------------------------------------'
PROC_NAME='abc'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"
PROC_NAME='abcdef'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"

이것은 준다

abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]


답변

사소하지만 작동하는 솔루션 :

echo -e "---------------------------- [UP]\r$PROC_NAME "


답변

이것이 가장 간단한 해결책이라고 생각합니다. 순수 쉘 내장, 인라인 수학 없음. 이전 답변에서 차용합니다.

부분 문자열과 $ {# …} 메타 변수 만 있습니다.

A="[>---------------------<]";

# Strip excess padding from the right
#

B="A very long header"; echo "${A:0:-${#B}} $B"
B="shrt hdr"          ; echo "${A:0:-${#B}} $B"

생산

[>----- A very long header
[>--------------- shrt hdr


# Strip excess padding from the left
#

B="A very long header"; echo "${A:${#B}} $B"
B="shrt hdr"          ; echo "${A:${#B}} $B"

생산

-----<] A very long header
---------------<] shrt hdr


답변

을 사용하여 공백으로 채울 수있는 방법은 없습니다 printf. 다음을 사용할 수 있습니다 sed.

printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'


답변

echo -n "$PROC_NAME $(printf '\055%.0s' {1..40})" | head -c 40 ; echo -n " [UP]"

설명:

  • printf '\055%.0s' {1..40}-40 개의 대시 생성
    (대시는 옵션으로 해석되므로 대신 이스케이프 된 ASCII 코드 사용)
  • "$PROC_NAME ..." -$ PROC_NAME 및 대시 연결
  • | head -c 40 -문자열을 처음 40 자까지 자르기

답변

이것은 더 간단하고 외부 명령을 실행하지 않습니다.

$ PROC_NAME="JBoss"
$ PROC_STATUS="UP"
$ printf "%-.20s [%s]\n" "${PROC_NAME}................................" "$PROC_STATUS"

JBoss............... [UP]