【动机】
我们在执行大量 linux shell 脚本或命令时, 常常少不了超前打印一些提示或表示正在执行之类的文本, 为避免单调, 有时候需要将文本做一些右对齐或居中显示, 而如果不指定位置, echo / printf 默认只是在当前位置顺序打印.
有了第二节的字符串占宽, 对齐输出不再是难事.
【意图】
指定输出命令或函数, 包括 echo 和第一节的颜色文本函数; 指定左对齐(默认), 居中或右对齐; 在当前行打印指定字符串
【实现】
注意到指定命令/函数, 以及指定对齐方式(左对齐 / 居中 / 有对齐), 均需要包含输入字符串的防误操作及默认处理, 故在 data.sh 中, 新建函数 available_range, 以供后续调用:
:<<COMMENT
尽量返回期待值, 如果期待值不在指定范围则返回默认值
$1 : 期待值
$2 : 默认值
$3 及以后: 允许范围值
使用: available_range <expected> <default> <list>
其中 list 与 index_in_strings 相同
返回值: 优先考虑期待数据, 不合格则返回默认值
COMMENT
available_range(){
local expect="$1" defv="$2"
shift 2
[ $(index_in_strings "$expect" $@) == -1 ] && echo $defv || echo $expect
}
函数比较简单, 不做过多解释(其中调用的 index_in_strings, 在花式清屏中有论述). 然后是在 console.sh 中做好可用的输出函数的声明:
# 除了 echo, 其他可用的输出方式
__AVAI_OP__=(
caption
menu
notice
tip
success
info
warn
error
critical
)
下面是 console.sh 中的 aop 函数( align output 之意):
:<<COMMENT
aop, 即 align output, 屏幕对齐打印
$1: comdline, 输出要使用的命令 / 函数, 可以带 echo 接受的选项: -n -e,
但要求带选项时, 必须用引号包围起来. 例如 'info -ne' , 'success -e' 等等.
默认为 echo, 其他可用值参见 __AVAI_OP__
$2: align 对齐方式, 默认为 left. 其他可用值为: center right
$3 及以后: str 要输出的字符串
用法 aop <func=echo?|warn|info|success|menu|critical|error|caption...> <align=left?> <str1> <str2>...
注意: 支持在文本中重新指定颜色, 此处颜色优先于指定的函数的自带颜色.
COMMENT
aop(){
# 允许打印方法带原生 echo 可用的选项, 例如 -n -e , 所以, 需要先剥离出方法名
local arr_cmdline
read -ra arr_cmdline <<<"$1"
local func=$(available_range "${arr_cmdline[0]}" 'echo' $(echo ${__AVAI_OP__[@]}))
# 选项: 即使长度为 1, 或甚至 0, 也不报错
local opts=${arr_cmdline[@]:1:$[${#arr_cmdline[@]}-1]}
# 对齐方式
local align=$(available_range "$2" left right left center)
shift 2
# 如果文本中重新指定了颜色, 则计算文本总占列, 应去除这些表示颜色的标识
local valids=$(echo "$@" | sed -r 's/(\\e|\\033)\[[0-9;]+m//g')
local w=$(cols_in_screen "$valids")
log_critical "<$@>, width:$w"
local cols=$(tput cols)
local rest=$[cols-w]
# 如果字符串太长以至于大于屏幕列数, 则指定的对齐是没有意义的.
if [[ $rest -gt 1 && ( $align == center || $align == right ) ]]; then
[ $align == center ] && rest=$[rest/2]
# 通过打印若干空格后再打印文本的方式实现对齐. \r: 保证对齐从屏幕第一列算起
printf "\r%${rest}s"
fi
$func $opts "$@"
}
【测试】
新建 test.sh
# 根据实际文件位置修改路径
source ./system.sh
source ./data.sh
source ./console.sh
way1(){
local strs=("If you want to continue using the Docker Hub API"
"中文 mixin english 以及罗马字母 γδεζη"
"有网民使用AI生成功能制造...")
local aln cmd
for cmd in tip success; do
for aln in left center right; do
for str in "${strs[@]}"; do
aop $cmd $aln $str
done
done
done
aop info center "一般常用居中格式, 最后加入换行"
aop 'notice -n' center "居中, 但末尾不换行"
echo "........结束行"
}
way1
运行结果如下:

【另类】
下面尝试在文本中重新指定颜色:
# 根据实际文件位置修改路径
source ./system.sh
source ./data.sh
source ./console.sh
way2(){
echo
local core_str="这是一段好长好长的居中文本 testing text..."
local str1="\e[31;44;5m$core_str\e[0m"
local str2="\033[35;42;1m$core_str\e[0m"
aop 'info -e' center "$core_str"
aop 'info -e' center "$str1"
aop 'info -e' center "$str2"
}
way2
输出结果:

可见, 颜色被重新指定, 居中属性也未受影响.
谢谢观看!