盒子!

盒子!

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

有没有办法可以改进它或实施替代解决方案?

这是使用字符串参数“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 $@

答案1

由于您的 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
}

当然,如果你愿意的话,你可以对其进行优化。

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

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
}

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

答案2

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

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

它正在发挥作用:

$ banner "hi"
######
# hi #
######
$ banner "hi there"
############
# hi there #
############

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

答案3

盒子!

$ echo 'Love Unix & Linux' | boxes -d stone -p a2v1
+---------------------+
|                     |
|  Love Unix & Linux  |
|                     |
+---------------------+

自从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  |
|                                 |
+---------------------------------+

如果这是在终端中,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  |$
|                                 |$
+---------------------------------+$

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

但应该注意的是,如果您使用类似的程序lolcat 外部boxes,输出看起来像这样

$ echo 'Love Unix & Linux' | boxes -d stone -p a2v1 | lolcat -f
+---------------------+
|                     |
|  Love Unix & Linux  |
|                     |
+---------------------+

但盒子和文字都是彩虹色的。

幸好我还没有制作自己的边框设计,其中包含颜色代码,因为我想边框设计也会遇到同样的问题。

居中文本、ASCII 艺术和方框!!!

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

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

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

并用它来居中一行文本。

center 'Love Unix & Linux'

对于使用多行且必须固定到位的 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"

但如果您喜欢使用诸如 之类的功能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'

对于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

显着的问题

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

答案4

我最近刚用过manatwork 的多行框答案在我的项目中,我将其修改为可以创建横幅 - 文本居中,没有边缘,甚至采用 BASH 颜色参数(可选的第二个参数可以更改文本的颜色)。我为我想在项目中使用的每种 bash 颜色创建了标签(即 RED='\e[31m')

# Multi line banners are generated like `banner ${COLOR} ${OPTIONAL_SECONDCOLOR} "first line" "second line" "third line"`
function banner() {
    local s=("${@:3}") b w
    local second_color=$2
    if [[ ! "$second_color" =~ "\e[".* ]]; then #If the second color isn't declared, then make the function use only the first color declared
        local s=("${@:2}") b w
        local second_color=$1
    fi

    for l in "${s[@]}"; do
        ((w<${#l})) && { b="         $l         "; w="${#l}"; }
    done
    echo -ne $1
    echo "-${b//?/-}-"
    for l in "${s[@]}"; do
        printf '         %s%*s%s         \n' "$(echo -ne $second_color)" "-$w" "$l" "$(echo -ne $1)"
    done
    echo -e "-${b//?/-}-${NC}"
}

用法示例:

banner ${LIGHT_PURPLE} "test here something line 1. SUPER LONG AND IT REALLY NEEDS TO BE LONG" "super duper long line 2" # Single Color option
banner ${LIGHT_PURPLE} ${RED} " This should be red now test here something line 1. SUPER LONG AND IT REALLY NEEDS TO BE LONG" "super duper long line 2" #Two Color Option

代码结果: 横幅代码的结果

相关内容