我正在编写一个bash shell脚本来显示进程是否正在运行。
到目前为止,我得到了这个:
printf "%-50s %s\n" $PROC_NAME [UP]
代码给了我这个输出:
JBoss [DOWN]
GlassFish [UP]
verylongprocessname [UP]
我想用' - '或'*'填补两个字段之间的空白,以使其更具可读性。如何在不影响田地对齐的情况下做到这一点?
我想要的输出是:
JBoss ------------------------------------------- [DOWN]
GlassFish --------------------------------------- [UP]
verylongprocessname ----------------------------- [UP]
答案 0 :(得分:65)
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// /-}
因此,pad(padlimit
和padlength
)可以基于终端宽度($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"
答案 1 :(得分:60)
Pure Bash。使用'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}}"
这给出了
abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]
答案 2 :(得分:14)
琐碎(但有效)的解决方案:
echo -e "---------------------------- [UP]\r$PROC_NAME "
答案 3 :(得分:13)
我认为这是最简单的解决方案。纯壳内置,没有内联数学。它借鉴了之前的答案。
只是子串和$ {#...}元变量。
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
答案 4 :(得分:11)
使用printf
无法使用空格填充任何内容。您可以使用sed
:
printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
答案 5 :(得分:8)
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个字符答案 6 :(得分:7)
这个更简单,并且不执行任何外部命令。
$ PROC_NAME="JBoss"
$ PROC_STATUS="UP"
$ printf "%-.20s [%s]\n" "${PROC_NAME}................................" "$PROC_STATUS"
JBoss............... [UP]
答案 7 :(得分:4)
仅使用echo
@Dennis Williamson的工作人员工作得很好,除了我试图用echo做这件事。 Echo允许输出具有特定颜色的charcacters。使用printf将删除该着色并打印不可读的字符。这是echo
- 唯一的选择:
string1=abc
string2=123456
echo -en "$string1 "
for ((i=0; i< (25 - ${#string1}); i++)){ echo -n "-"; }
echo -e " $string2"
输出:
abc ---------------------- 123456
当然,您可以使用@Dennis Williamson提出的所有变体,无论您希望正确的部分是左对齐还是右对齐(将25 - ${#string1}
替换为25 - ${#string1} - ${#string2}
等等。
答案 8 :(得分:2)
这是另一个:
$ { echo JBoss DOWN; echo GlassFish UP; } | while read PROC STATUS; do echo -n "$PROC "; printf "%$((48-${#PROC}))s " | tr ' ' -; echo " [$STATUS]"; done
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
答案 9 :(得分:2)
如果要在某个固定列号处结束填充字符,则可以覆盖并cut
长度:
# Previously defined:
# PROC_NAME
# PROC_STATUS
PAD="--------------------------------------------------"
LINE=$(printf "%s %s" "$PROC_NAME" "$PAD" | cut -c 1-${#PAD})
printf "%s %s\n" "$LINE" "$PROC_STATUS"
答案 10 :(得分:1)
具有自动缩放/调整大小方法和示例的简单控制台跨度/填充/填充/填充。
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" "$1" "$spanner" "$2";
}
示例: create-console-spanner "loading graphics module" "[success]"
现在,这是一个全功能颜色字符终端套件,它可以完成有关用扳手打印颜色和样式格式的字符串的所有操作。 / p>
# Author: Triston J. Taylor <pc.wiz.tt@gmail.com>
# 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//$1/$2}"
}
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` - ${2}))
eval printf \'"%0.1s"\' "${1:0:1}"{1..$l}
}
function paint-span() {
local left_format=$1 right_format=$3
local left_length=$(paint-format -l "$left_format") right_length=$(paint-format -l "$right_format")
paint-format "$left_format";
paint-get-spanner "$2" $(( 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 [[ "$1" == "-v" ]]; then OPTIONS=" -v $2"; MODE=$PRINT_VAR; shift 2; continue; fi;
if [[ "$1" == "-l" ]]; then OPTIONS=" -v VAR"; MODE=$PRINT_SIZE; shift 1; continue; fi;
done;
OPTIONS+=" --"
local format="$1"; 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";
}
要打印颜色,这很简单:paint-format "&red;This is %s\n" red
而且,您以后可能想在以下地方加粗体:paint-format "&bold;%s!\n" WOW
-l
函数的paint-format
选项可测量文本,以便您可以进行控制台字体指标操作。
-v
函数的paint-format
选项与printf
相同,但不能与-l
一起提供
现在可以进行扩展!
paint-span "hello " . " &blue;world"
[注意:我们没有添加换行符末尾序列,但是文本填充了终端符,因此下一行似乎只是换行符末尾序列]
的输出是:
hello ............................. world
答案 11 :(得分:1)
简单但确实可以:
printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
用法示例:
while read PROC_NAME STATUS; do
printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
done << EOT
JBoss DOWN
GlassFish UP
VeryLongProcessName UP
EOT
输出到标准输出:
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
VeryLongProcessName ------------------------------ [UP]
答案 12 :(得分:0)
Bash + seq以允许参数扩展
类似于@Dennis Williamson的答案,但是如果seq
可用,则无需对填充字符串的长度进行硬编码。以下代码允许将变量作为位置参数传递给脚本:
COLUMNS="${COLUMNS:=80}"
padlength="${1:-$COLUMNS}"
pad=$(printf '\x2D%.0s' $(seq "$padlength") )
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
使用ASCII代码“ 2D”代替字符“-”,以避免shell将其解释为命令标志。另一个选项是“ 3D”以使用“ =“。
在没有作为参数传递任何填充长度的情况下,以上代码默认为80个字符的标准终端宽度。
要利用bash shell变量COLUMNS
(即当前终端的宽度),脚本需要使用环境变量。一种方法是通过执行前面带有.
(“点”命令)的脚本来获取所有环境变量,如下所示:
. /path/to/script
或(更好)在执行时显式传递COLUMNS
变量,如下所示:
/path/to/script $COLUMNS