bash 脚本,在框中回显输出

Rah*_*til 9 shell-script tput printf

我创建了这个函数,它打印输出,如示例图像中所示。但是,这个功能的实现似乎太复杂了。

有什么方法可以改进它或实施替代解决方案吗?

这是执行带有字符串参数“Love Unix & Linux”的“box_out”函数后的输出示例

#!/bin/bash
function box_out() {
    input_char=$(echo "$@" | wc -c)
    line=$(for i in `seq 0 $input_char`; do printf "-"; done)
    # tput This should be the best option. what tput does is it will
    # read the terminal info and render the correctly escaped ANSI code
    # for you.
    # Code like \033[31m will break the readline library in some of the
    # terminals.
    tput bold
    line="$(tput setaf 3)${line}"
    space=${line//-/ }
    echo " ${line}"
    printf '|' ; echo -n "$space" ; printf "%s\n" '|';
    printf '| ' ;tput setaf 4; echo -n "$@"; tput setaf 3 ; printf "%s\n" ' |';
    printf '|' ; echo -n "$space" ; printf "%s\n" '|';
    echo " ${line}"
    tput sgr 0
}

box_out $@
Run Code Online (Sandbox Code Playgroud)

man*_*ork 16

由于您的 shebang 和语法表明 unportable bash,我更喜欢这样:

function box_out()
{
  local s="$*"
  tput setaf 3
  echo " -${s//?/-}-
| ${s//?/ } |
| $(tput setaf 4)$s$(tput setaf 3) |
| ${s//?/ } |
 -${s//?/-}-"
  tput sgr 0
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以根据需要对其进行优化。

根据评论中的要求进行更新,以处理多行文本。

function box_out()
{
  local s=("$@") b w
  for l in "${s[@]}"; do
    ((w<${#l})) && { b="$l"; w="${#l}"; }
  done
  tput setaf 3
  echo " -${b//?/-}-
| ${b//?/ } |"
  for l in "${s[@]}"; do
    printf '| %s%*s%s |\n' "$(tput setaf 4)" "-$w" "$l" "$(tput setaf 3)"
  done
  echo "| ${b//?/ } |
 -${b//?/-}-"
  tput sgr 0
}
Run Code Online (Sandbox Code Playgroud)

使用多个参数调用它,例如box_out 'first line' 'more line' 'even more line'.

  • 太棒了…………你是师父…… (2认同)

rob*_*bru 9

所以,我的解决方案与你的不太一样,但严格来说它在文本周围打印一个框,而且实现更简单,所以我想我会分享。

banner() {
    msg="# $* #"
    edge=$(echo "$msg" | sed 's/./#/g')
    echo "$edge"
    echo "$msg"
    echo "$edge"
}
Run Code Online (Sandbox Code Playgroud)

这是在行动:

$ banner "hi"
######
# hi #
######
$ banner "hi there"
############
# hi there #
############
Run Code Online (Sandbox Code Playgroud)

只是纯文本,没有花哨的ansi颜色或任何东西。


JRC*_*ney 6

盒子!

$ echo 'Love Unix & Linux' | boxes -d stone -p a2v1
+---------------------+
|                     |
|  Love Unix & Linux  |
|                     |
+---------------------+
Run Code Online (Sandbox Code Playgroud)

由于boxes需要将文本作为文件发送给它,我建议使用上面示例中的语法,其中文本boxes通过echo.

“为什么boxes?”

使用它很容易。只需告诉它您想使用哪种边框设计以及您希望它如何显示,您就完成了。

当然,如果你想有创意,你可以制作自己的设计。这真的很容易而且很有趣。使用的唯一缺点boxes是我还没有弄清楚如何将生成的框boxes居中以将中心与屏幕对齐,尽管有一个 bash hack

“颜色呢?”

最初的问题已经证明了颜色代码的使用。因此,展示如何boxes处理这个问题似乎是正确的。

虽然tput很受欢迎,但我认为自己是一个老派的 Bash 人,仍然喜欢使用转义命令。我敢肯定 StackExchange 有一些人会反对它,但每个人都反对。无论如何,我愿意抛开我的个人偏好,包括另一个这样做的例子tput

自然,我认为第一步是设置内部文本的颜色。所以让我们先这样做。

printf "$(tput setaf 4)Love Unix & Linux$(tput sgr 0)" | boxes -d stone -p a2v1
+---------------------------------+
|                                 |
|  Love Unix & Linux  |
|                                 |
+---------------------------------+
Run Code Online (Sandbox Code Playgroud)

如果这是在终端中,Love Unix & Linux将是蓝色的……但是正如您所看到的,boxes处理得不好。所以没出什么问题?

printf "$(tput setaf 4)Love Unix & Linux$(tput sgr 0)" | boxes -d stone -p a2v1 | cat -A
+---------------------------------+$
|                                 |$
|  ^[[34mLove Unix & Linux^[(B^[[0m  |$
|                                 |$
+---------------------------------+$
Run Code Online (Sandbox Code Playgroud)

通过显示隐藏字符进行仔细检查,cat -A显示boxes假定框的长度包括文本和转义字符的长度。

但应该注意的是,如果您使用诸如外部的程序,则输出如下所示lolcat boxes

$ echo 'Love Unix & Linux' | boxes -d stone -p a2v1 | lolcat -f
+---------------------+
|                     |
|  Love Unix & Linux  |
|                     |
+---------------------+
Run Code Online (Sandbox Code Playgroud)

但是框和文本为彩虹色。

这是一件好事,我还没有制作自己的边框设计,其中包含颜色代码,因为我认为边框设计会遇到同样的问题。

居中文本、ASCII 艺术和盒子!!!

另一个缺陷boxes是,如果您知道如何使用 Bash 将文本居中到终端的 with ,boxes则仍会将框与屏幕左侧对齐。弄清楚了。

当您想要将不在框中的文本居中时,您可以简单地使用

center(){
  COLS=$(tput cols)  # use the current width of the terminal.
  printf "%*s\n" "$(((${#1}+${COLS})/2))" "$1"
}
Run Code Online (Sandbox Code Playgroud)

并使用它来居中一行文本。

center 'Love Unix & Linux'
Run Code Online (Sandbox Code Playgroud)

对于使用多行且必须固定到位的 ascii-art,有此选项。

# Rather than removing text, even things out by padding lines with spaces
draw_banner(){
  local banner="$1"
  # Banner Width
  BW=$(cat $banner | awk '{print length}' | sort -nr | head -1)

  while IFS= read -r line; do
    line=$(echo "${line}" | sed -n -e 's/^  / /g;p')
    line=$(printf "%-${BW}s" "${line}")
    center "${line}"  # our center function from earlier.
  done < "$banner"
}

draw_banner "path/to/your_ascii_art_logo.txt"
Run Code Online (Sandbox Code Playgroud)

但是,如果您喜欢使用诸如 之类的东西figlet,则不需要使用这些功能,因为该-c选项提供了居中选项。

$figfontdir="path/to/figlet/fonts"
$figfont="Alligator"
text_banner(){
  COLS=$(tput cols)  # use the width of the terminal!
  figlet -d "$figfontdir" -f "$figfont" -k -w $COLS -c "$1"
}

text_banner 'Love Unix & Linux'
Run Code Online (Sandbox Code Playgroud)

对于boxes,我们做了类似的事情,draw_banner()但我们需要管道数据!

# Center a box created with `boxes
# It's like draw_banner, but `<<<` reads a string of data rather than a file.
$boxfile="/path/to/your_box_designs.box" # or ".txt". I like ".box".
$boxdesgin="stone"
center_box(){
  local data="$(</dev/stdin)"  # Read from standard input
  # Banner Width
  BW=$(cat <<< ${data} | awk '{print length}' | sort -nr | head -1)

  while IFS= read -r line; do
    line=$(echo "${line}" | sed -n -e 's/^  / /g;p')
    line=$(printf "%-${BW}s" "${line}")
    center "${line}"  # our center command from earlier.
  done <<< "${data}"
}

(
 # A bunch of stuff to center!
) | boxes -f $boxfile -d $boxdesign -a hcvcjc | center_box
Run Code Online (Sandbox Code Playgroud)

显着的问题

解决这两个问题,UTF/ANSI 字符问题不仅可以boxes为将文本封装在 ASCII 框中提供更好的解决方案,而且可以提供一种可以调用的创造性替代方法,而不是手动编码框。