Edw*_*ard 6 linux unix bash shell
新手来了 我正在寻找 bash 脚本来居中和对齐文本。我的脚本只适用于一行文本。你会如何改进它?
#!/bin/bash
COLS=$(tput cols)
while true; do
clear
echo -n "Type text "
read text
echo
echo "Menu"
echo "1) Right justify "
echo "2) Center "
echo "3) Exit "
echo
echo -n "Choose [1-3]: "
read opt
echo
case $opt in
1) printf "%*s\n" $COLS "$text"
break
;;
2) printf "%*s\n" $[$COLS/2] "$text"
break
;;
3) break
;;
*)
echo "Error. Press [1-3]"
break
;;
esac
done
Run Code Online (Sandbox Code Playgroud)
正如您所发现的,$COLUMNS仅在交互式-ishell 中才有用,因此我们columns="$(tput cols)"改为使用。
我唯一的问题是下面的行。它不居中文本。
printf "%*s\n" $[$COLS/2] "$text"
扩展您的工作,这是一个显示居中文本(来自文件)的功能。要在脚本中调用它,请使用display_center "file.txt"
display_center(){
columns="$(tput cols)"
while IFS= read -r line; do
printf "%*s\n" $(( (${#line} + columns) / 2)) "$line"
done < "$1"
}
Run Code Online (Sandbox Code Playgroud)
请注意使用${#line}(类似于wc -m)来计算行中的字符数。只要您只需要显示没有颜色/格式的纯文本,那么这应该可以正常工作。
这是一个使用相同的 printf 实现显示右对齐文本(来自文件)的函数。
display_right(){
columns="$(tput cols)"
while IFS= read -r line; do
printf "%*s\n" $columns "$line"
done < "$1"
}
Run Code Online (Sandbox Code Playgroud)
你也可以用 tput 和 echo 做类似的事情,但下面的例子不是那么健壮(即会因长字符串而失败)。
row=0
col=$(( ($(tput cols) - ${#text}) / 2))
tput clear
tput cup $row $col
echo "$text"
Run Code Online (Sandbox Code Playgroud)
此外,您可能需要考虑使用dialog或select生成菜单。这将使您的脚本更加清晰。
http://bash.cyberciti.biz/guide/Select_loop
https://serverfault.com/questions/144939/multi-select-menu-in-bash-script
#!/usr/bin/awk -f
{
z = 92 - length
y = int(z / 2)
x = z - y
printf "%*s%s%*s\n", x, "", $0, y, ""
}
Run Code Online (Sandbox Code Playgroud)
输入
你好世界 阿尔法布拉沃查理三角洲
输出
你好世界
阿尔法布拉沃查理三角洲
我已经从编写脚本中获得乐趣有一段时间了。我是一名木匠和机械师,所以对我来说很裸露,哈哈。我知道这是一个老问题,但我最近正在寻找类似的东西来想象一个我一直在研究的过于复杂的 Arch 安装脚本,但从未找到适合我需求的答案。因此,我编写了一个(可能是黑客式的)函数,它提供了一些选项来简化我正在寻找的格式。我想如果有人感兴趣的话我会分享。这一切都是在 zsh 中完成的。
# Formatting using printf
#
# _L == total length for 'L' and 'R' options
# tl == total length for 'C' option
# _c == center for 'C' option ( tl / 2 )
# fill == filler character or space by default
#
# Default lengths declared at top of function
#
# usage $) f_M [string] [L,R,C] [character count]
# -S option:
# $) f_M -S [character] [total length (- for default 'space')]
# -3rd var ($3) is needed for filler character ($2) or
# else ($2) is total length
#
#
f_M () {
tl=72
_c=36
_L=16
f_numread () {
printf $1 | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'
}
f_C () {
local x=$(printf $1 | wc -c)
local y=$(expr $_c - $(expr $x / 2))
local z=$(expr $tl - $y)
local space=' '
printf "%${y}s%-${z}s\n" "$space" "$1"
}
case $1 in
-S)
fill=' '
if [[ -n $2 ]]; then
if [[ -n $3 ]]; then
fill="$2"
if [[ $3 =~ ^-?[0-9]+$ ]]; then
tl=$3
fi
else
if [[ $2 =~ ^-?[0-9]+$ ]]; then
tl=$2
fi
fi
fi
printf "${fill}%.0s" {1..$tl}
;;
*)
if [[ $3 =~ ^-?[0-9]+$ ]]; then
tl=$3
_L=$3
_c=$(expr $tl / 2)
fi
if [[ $1 =~ ^-?[0-9]+$ ]]; then
local x=$(f_numread $1)
case $2 in
L)
printf "%-${_L}s\n" "$x" ;;
R)
printf "%${_L}s\n" "$x" ;;
C)
f_C $x ;;
"")
printf '%s\n' $x
esac
else
case $2 in
L)
printf "%-${_L}s\n" "$1" ;;
R)
printf "%${_L}s\n" "$1" ;;
C)
f_C $1 ;;
"")
printf '%s\n' $1
esac
fi
;;
esac
}
Run Code Online (Sandbox Code Playgroud)
这是我如何使用它的一些示例......
# Default character length is 72
[user@arch]$ printf '%s\n' "<$(f_M -S)>"
< >
[user@arch]$ printf '%s\n' "<$(f_M -S = 50)>"
<==================================================>
# To change the 'fill' character(s), a 3rd argument is required
# So I set '-' to keep my default value
# There is probably a better way to do it but this fit my needs
[user@arch]$ printf '%s\n' "<$(f_M -S = -)>"
<========================================================================>
# Because of what I was trying to do and to get multiple uses out of
# one function, I use separate variables for 'C' than for 'L' and 'R'
[user@arch]$ printf '%s\n%s\n%s\n' "<$(f_M 'left' L 72)>" \
"<$(f_M 'center' C)>" "<$(f_M 'right' R 72)>"
<left >
< center >
< right>
# It will also take a string that is only numbers and make
# it more "human readable"
[user@arch]$ num=12345678
[user@arch]$ printf '%s\n' "<$(f_M ${num} C 50)>"
< 12,345,678 >
Run Code Online (Sandbox Code Playgroud)
为了获得更多创意,我可以添加另一个函数,该函数将使用数组自动创建一个精美的文本框......
#!/bin/zsh
f_fancy_box () {
local s=''
for s in ${text[@]}; do
case $s in
000) printf '%b\n' "<$(f_M -S = -)>" ;;
---) printf '%b\n' "| $(f_M -S - 70) |" ;;
*) printf '%b\n' "|$(f_M $s C)|" ;;
esac
done
}
text=(
"000"
" "
"It is hobbies like this"
"that keep me from ever"
"getting any sleep lol"
" "
"---"
" "
"But I think"
"it is worth it"
":P"
" "
"000"
)
f_fancy_box
exit
Run Code Online (Sandbox Code Playgroud)
输出:
<========================================================================>
| |
| It is hobbies like this |
| that keep me from ever |
| getting any sleep lol |
| |
| ---------------------------------------------------------------------- |
| |
| But I think |
| it is worth it |
| :P |
| |
<========================================================================>
Run Code Online (Sandbox Code Playgroud)
我希望有人觉得这很有用!
编辑:将 f_fancy_box 中的 printf '%s' 更改为 '%b'。根据 printf 的手册页,并允许字符转义,我认为这实际上是合适的命令。如果我错了有人纠正我...