在printf中填充字符

cor*_*ish 98 bash shell printf

我正在编写一个bash shell脚本来显示进程是否正在运行.

到目前为止,我得到了这个:

printf "%-50s %s\n" $PROC_NAME [UP]
Run Code Online (Sandbox Code Playgroud)

代码给了我这个输出:

JBoss                                              [DOWN]

GlassFish                                          [UP]

verylongprocessname                                [UP]
Run Code Online (Sandbox Code Playgroud)

我想用' - '或'*'填补两个字段之间的空白,使其更具可读性.如何在不扰乱田地对齐的情况下做到这一点?

我想要的输出是:

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

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

verylongprocessname -----------------------------  [UP]
Run Code Online (Sandbox Code Playgroud)

Pau*_*ce. 69

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
Run Code Online (Sandbox Code Playgroud)

不幸的是,在该技术中,垫片的长度必须被硬编码为比您认为需要的最长的片段长,但是padlength可以是如图所示的变量.但是,您可以使用这三个替换第一行,以便能够使用垫的长度变量:

padlimit=60
pad=$(printf '%*s' "$padlimit")
pad=${pad// /-}
Run Code Online (Sandbox Code Playgroud)

因此,pad(padlimitpadlength)可以基于终端宽度($COLUMNS)或从最长数据串的长度计算.

输出:

a--------------------------------bbbbbbb
aa--------------------------------bbbbbb
aaaa-------------------------------bbbbb
aaaaaaaa----------------------------bbbb
Run Code Online (Sandbox Code Playgroud)

不减去第二个字符串的长度:

a---------------------------------------bbbbbbb
aa--------------------------------------bbbbbb
aaaa------------------------------------bbbbb
aaaaaaaa--------------------------------bbbb
Run Code Online (Sandbox Code Playgroud)

第一行可以是等价的(类似于sprintf):

printf -v pad '%0.1s' "-"{1..60}
Run Code Online (Sandbox Code Playgroud)

或类似的更动态的技术:

printf -v pad '%*s' "$padlimit"
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以在一行上进行打印:

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

  • @EdouardLopez:第一个星号被参数列表中的零替换.第二个星号由第二个参数中的计算结果替换.例如,字符串"aaaa"和"bbbbb"的结果是"%0.31s".字符串(最后一个参数)被截断为点后指定的长度.零可防止输出任何空间填充.因此输出了31个连字符. (3认同)
  • 您能解释一下 printf '%*.*s' ... 部分吗? (2认同)

Fri*_*ner 64

纯粹的狂欢.使用'PROC_NAME'值的长度作为固定字符串'line'的偏移量:

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}}"
Run Code Online (Sandbox Code Playgroud)

这给了

abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]
Run Code Online (Sandbox Code Playgroud)

  • 神奇之处在于 ${line:${#PROC_NAME}},它使用 bash 子字符串提取来仅从变量 line 的某个点开始返回,该点设置为从 PROC_NAME 中的字符数开始。https://www.tldp.org/LDP/abs/html/string-manipulation.html#SUBSTREXTR01 (3认同)

Nic*_*oni 16

琐碎(但工作)的解决方案:

echo -e "---------------------------- [UP]\r$PROC_NAME "
Run Code Online (Sandbox Code Playgroud)

  • 但只在终端上.如果将输出发送到文件,那将是一团糟. (4认同)
  • 那么你真正期望从一个简单的解决方案?!?完全工作也与输出重定向?!?]:P (4认同)

syn*_*tel 14

我认为这是最简单的解决方案.纯壳内置,没有内联数学.它借鉴了之前的答案.

只是子串和$ {#...}元变量.

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"
Run Code Online (Sandbox Code Playgroud)

产生

[>----- 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"
Run Code Online (Sandbox Code Playgroud)

产生

-----<] A very long header
---------------<] shrt hdr
Run Code Online (Sandbox Code Playgroud)


F'x*_*F'x 11

除了空间使用之外,没有办法填充任何东西printf.你可以使用sed:

printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
Run Code Online (Sandbox Code Playgroud)

  • +1如果PROC_NAME包含短划线,则会出现问题 - 使用额外的@:`printf"%-50s @%s \n"$ {PROC_NAME} @ [UP]很容易解决 sed -e's// - /g'-e's/ - @//'-e's/@ - //'` (7认同)

dra*_*nHR 9

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

说明:

  • printf '\055%.0s' {1..40}- 创建40个破折号
    (破折号被解释为选项,因此使用转义的ascii代码)
  • "$PROC_NAME ..." - 连接$ PROC_NAME并破折号
  • | head -c 40 - 将字符串修剪为前40个字符


Cha*_*ano 7

这个更简单,并且不执行任何外部命令.

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

JBoss............... [UP]
Run Code Online (Sandbox Code Playgroud)


Lui*_*iel 7

Simple but it does work:

printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
Run Code Online (Sandbox Code Playgroud)

Example of usage:

while read PROC_NAME STATUS; do  
    printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
done << EOT 
JBoss DOWN
GlassFish UP
VeryLongProcessName UP
EOT
Run Code Online (Sandbox Code Playgroud)

Output to stdout:

JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
VeryLongProcessName ------------------------------ [UP]
Run Code Online (Sandbox Code Playgroud)


Chr*_*aes 5

echo只使用

@Dennis Williamson 的回答者工作得很好,只是我试图使用 echo 来做到这一点。Echo 允许输出具有特定颜色的字符。使用 printf 将删除该颜色并打印不可读的字符。这是echo唯一的选择:

string1=abc
string2=123456
echo -en "$string1 "
for ((i=0; i< (25 - ${#string1}); i++)){ echo -n "-"; }
echo -e " $string2"
Run Code Online (Sandbox Code Playgroud)

输出:

abc ---------------------- 123456
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用@Dennis Williamson 提出的所有变体,无论您希望右侧部分是左对齐还是右对齐(替换25 - ${#string1}25 - ${#string1} - ${#string2}等...