bash printf 中的填充字符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4409399/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Padding characters in printf
提问by cordish
I am writing a bash shell script to display if a process is running or not.
我正在编写一个 bash shell 脚本来显示进程是否正在运行。
So far, I got this:
到目前为止,我得到了这个:
printf "%-50s %s\n" $PROC_NAME [UP]
The code gives me this output:
代码给了我这个输出:
JBoss [DOWN]
GlassFish [UP]
verylongprocessname [UP]
I want to pad the gap between the two fields with a '-' or '*' to make it more readable. How do I do that without disturbing the alignment of the fields?
我想用“-”或“*”填充两个字段之间的间隙以使其更具可读性。如何在不干扰字段对齐的情况下做到这一点?
The output I want is:
我想要的输出是:
JBoss ------------------------------------------- [DOWN]
GlassFish --------------------------------------- [UP]
verylongprocessname ----------------------------- [UP]
回答by Paused until further notice.
Pure Bash, no external utilities
纯 Bash,无外部实用程序
This demonstration does full justification, but you can just omit subtracting the length of the second string if you want ragged-right lines.
这个演示做了充分的论证,但如果你想要参差不齐的行,你可以省略减去第二个字符串的长度。
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
Unfortunately, in that technique, the length of the pad string has to be hardcoded to be longer than the longest one you think you'll need, but the padlength can be a variable as shown. However, you can replace the first line with these three to be able to use a variable for the length of the pad:
不幸的是,在该技术中,pad 字符串的长度必须硬编码为比您认为需要的最长字符串长,但 padlength 可以是一个变量,如图所示。但是,您可以用这三行替换第一行,以便能够使用一个变量来表示焊盘的长度:
padlimit=60
pad=$(printf '%*s' "$padlimit")
pad=${pad// /-}
So the pad (padlimit
and padlength
) could be based on terminal width ($COLUMNS
) or computed from the length of the longest data string.
因此,pad ( padlimit
and padlength
) 可以基于终端宽度 ( $COLUMNS
) 或根据最长数据字符串的长度计算。
Output:
输出:
a--------------------------------bbbbbbb
aa--------------------------------bbbbbb
aaaa-------------------------------bbbbb
aaaaaaaa----------------------------bbbb
Without subtracting the length of the second string:
不减去第二个字符串的长度:
a---------------------------------------bbbbbbb
aa--------------------------------------bbbbbb
aaaa------------------------------------bbbbb
aaaaaaaa--------------------------------bbbb
The first line could instead be the equivalent (similar to sprintf
):
第一行可以是等价的(类似于sprintf
):
printf -v pad '%0.1s' "-"{1..60}
or similarly for the more dynamic technique:
或者类似的对于更动态的技术:
printf -v pad '%*s' "$padlimit"
You can do the printing all on one line if you prefer:
如果您愿意,您可以在一行上打印所有内容:
printf '%s%*.*s%s\n' "$string1" 0 $((padlength - ${#string1} - ${#string2} )) "$pad" "$string2"
回答by Fritz G. Mehner
Pure Bash. Use the length of the value of 'PROC_NAME' as offset for the fixed string 'line':
纯猛击。使用 '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}}"
This gives
这给
abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]
回答by Nicola Leoni
Trivial (but working) solution:
琐碎(但有效)的解决方案:
echo -e "---------------------------- [UP]\r$PROC_NAME "
回答by synthesizerpatel
I think this is the simplest solution. Pure shell builtins, no inline math. It borrows from previous answers.
我认为这是最简单的解决方案。纯 shell 内置函数,没有内联数学。它借鉴了以前的答案。
Just substrings and the ${#...} meta-variable.
只是子字符串和 ${#...} 元变量。
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"
Produces
生产
[>----- 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"
Produces
生产
-----<] A very long header
---------------<] shrt hdr
回答by F'x
There's no way to pad with anything but spaces using printf
. You can use sed
:
除了使用printf
. 您可以使用sed
:
printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
回答by draganHR
echo -n "$PROC_NAME $(printf '5%.0s' {1..40})" | head -c 40 ; echo -n " [UP]"
Explanation:
解释:
printf '\055%.0s' {1..40}
- Create 40 dashes
(dash is interpreted as option so use escaped ascii code instead)"$PROC_NAME ..."
- Concatenate $PROC_NAME and dashes| head -c 40
- Trim string to first 40 chars
printf '\055%.0s' {1..40}
- 创建 40 个破折号
(破折号被解释为选项,因此请改用转义的 ascii 代码)"$PROC_NAME ..."
- 连接 $PROC_NAME 和破折号| head -c 40
- 将字符串修剪为前 40 个字符
回答by Chad Juliano
This one is even simpler and execs no external commands.
这个更简单,不执行任何外部命令。
$ PROC_NAME="JBoss"
$ PROC_STATUS="UP"
$ printf "%-.20s [%s]\n" "${PROC_NAME}................................" "$PROC_STATUS"
JBoss............... [UP]
回答by Chris Maes
using echo
only
echo
只使用
The anwser of @Dennis Williamson is working just fine except I was trying to do this using echo. Echo allows to output charcacters with a certain color. Using printf would remove that coloring and print unreadable characters. Here's the echo
-only alternative:
@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"
output:
输出:
abc ---------------------- 123456
of course you can use all the variations proposed by @Dennis Williamson whether you want the right part to be left- or right-aligned (replacing 25 - ${#string1}
by 25 - ${#string1} - ${#string2}
etc...
当然,您可以使用@Dennis Williamson 提出的所有变体,无论您希望右侧部分是左对齐还是右对齐(替换25 - ${#string1}
为25 - ${#string1} - ${#string2}
等...
回答by Luis Daniel
Simple but it does work:
简单但确实有效:
printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
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
Output to stdout:
输出到标准输出:
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
VeryLongProcessName ------------------------------ [UP]
回答by Hypersoft Systems
Simple Console Span/Fill/Pad/Padding with automatic scaling/resizing Method and Example.
带有自动缩放/调整大小方法和示例的简单控制台跨度/填充/填充/填充。
function create-console-spanner() {
# 1: left-side-text, 2: right-side-text
local spanner="";
eval printf -v spanner \'"%0.1s"\' "-"{1..$[$(tput cols)- 2 - ${#1} - ${#2}]}
printf "%s %s %s" "" "$spanner" "";
}
Example:create-console-spanner "loading graphics module" "[success]"
例子:create-console-spanner "loading graphics module" "[success]"
Nowhere is a full-featured-color-character-terminal-suitethat does everything in regards to printing a color and style formatted string with a spanner.
现在这是一个功能齐全的颜色字符终端套件,它可以完成与使用扳手打印颜色和样式格式的字符串有关的所有工作。
# Author: Triston J. Taylor <[email protected]>
# Date: Friday, October 19th, 2018
# License: OPEN-SOURCE/ANY (NO-PRODUCT-LIABILITY OR WARRANTIES)
# Title: paint.sh
# Description: color character terminal driver/controller/suite
declare -A PAINT=([none]=`tput sgr0` [bold]=`tput bold` [black]=`tput setaf 0` [red]=`tput setaf 1` [green]=`tput setaf 2` [yellow]=`tput setaf 3` [blue]=`tput setaf 4` [magenta]=`tput setaf 5` [cyan]=`tput setaf 6` [white]=`tput setaf 7`);
declare -i PAINT_ACTIVE=1;
function paint-replace() {
local contents=$(cat)
echo "${contents///}"
}
source <(cat <<EOF
function paint-activate() {
echo "$@" | $(for k in ${!PAINT[@]}; do echo -n paint-replace \"\&$k\;\" \"${PAINT[$k]}\" \|; done) cat;
}
EOF
)
source <(cat <<EOF
function paint-deactivate(){
echo "$@" | $(for k in ${!PAINT[@]}; do echo -n paint-replace \"\&$k\;\" \"\" \|; done) cat;
}
EOF
)
function paint-get-spanner() {
(( $# == 0 )) && set -- - 0;
declare -i l=$(( `tput cols` - ))
eval printf \'"%0.1s"\' "${1:0:1}"{1..$l}
}
function paint-span() {
local left_format= right_format=
local left_length=$(paint-format -l "$left_format") right_length=$(paint-format -l "$right_format")
paint-format "$left_format";
paint-get-spanner "" $(( left_length + right_length));
paint-format "$right_format";
}
function paint-format() {
local VAR="" OPTIONS='';
local -i MODE=0 PRINT_FILE=0 PRINT_VAR=1 PRINT_SIZE=2;
while [[ "${1:0:2}" =~ ^-[vl]$ ]]; do
if [[ "" == "-v" ]]; then OPTIONS=" -v "; MODE=$PRINT_VAR; shift 2; continue; fi;
if [[ "" == "-l" ]]; then OPTIONS=" -v VAR"; MODE=$PRINT_SIZE; shift 1; continue; fi;
done;
OPTIONS+=" --"
local format=""; shift;
if (( MODE != PRINT_SIZE && PAINT_ACTIVE )); then
format=$(paint-activate "$format&none;")
else
format=$(paint-deactivate "$format")
fi
printf $OPTIONS "${format}" "$@";
(( MODE == PRINT_SIZE )) && printf "%i\n" "${#VAR}" || true;
}
function paint-show-pallette() {
local -i PAINT_ACTIVE=1
paint-format "Normal: &red;red &green;green &blue;blue &magenta;magenta &yellow;yellow &cyan;cyan &white;white &black;black\n";
paint-format " Bold: &bold;&red;red &green;green &blue;blue &magenta;magenta &yellow;yellow &cyan;cyan &white;white &black;black\n";
}
To print a color, that's simple enough: paint-format "&red;This is %s\n" red
And you might want to get bold later on: paint-format "&bold;%s!\n" WOW
要打印 color,这很简单:paint-format "&red;This is %s\n" red
稍后您可能想要加粗:paint-format "&bold;%s!\n" WOW
The -l
option to the paint-format
function measures the text so you can do console font metrics operations.
该函数的-l
选项paint-format
测量文本,以便您可以执行控制台字体度量操作。
The -v
option to the paint-format
function works the same as printf
but cannot be supplied with -l
该功能的-v
选项与paint-format
功能相同,printf
但不能提供-l
Now for the spanning!
现在为跨越!
paint-span "hello " . " &blue;world"
[note: we didn't add newline terminal sequence, but the text fills the terminal, so the next line only appears to be a newline terminal sequence]
paint-span "hello " . " &blue;world"
[注意:我们没有添加换行符终端序列,而是文本填满了终端,所以下一行只出现了一个换行终端序列]
and the output of that is:
其输出是:
hello ............................. world
hello ............................. world