箱!

箱!

サンプル画像に示されている出力を印刷するこの関数を作成しました。しかし、この機能の実装は複雑すぎるようです。

これを改善したり代替ソリューションを実装したりする方法はありますか?

以下は、文字列パラメータ「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 #
############

単なるテキストだけで、カラフルなアンシカラーや何もありません。

答え3

箱!

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

boxesテキストをファイルに送信する必要があるため、テキストboxesecho

「なぜboxes?」

それを使用するのは簡単です。使用したいボーダーのデザインと表示方法を教えてください。

もちろん、創造性を発揮したいなら、自分でデザインすることもできます。本当に簡単で楽しいです。使用の唯一の欠点は、bashハッキングがありますが、中央を画面に揃えるboxesために作成されたボックスを中央に合わせる方法が見つからなかったことです。boxes

「色はどうですか?」

元の質問はカラーコードの使用を示しています。したがって、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アート&ボックス! ! !

もう1つの欠点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

重要な問題

この2つの問題( UTF / ANSI文字の問題)を解決すると、boxesテキストをASCIIボックスにまとめるためのより良いソリューションを提供するだけでなく、ボックスを手動でエンコードするための創造的な代替手段も提供されます。

答え4

私は最近使用しました。Manatwork 複数行ボックスの回答私のプロジェクトでは、バナーを作成できるように修正しました。テキストが中央にあり、エッジがなく、BASHカラーパラメータも使用しました(オプションの2番目のパラメータはテキストの色を変更できます)。私のプロジェクトで使用したい各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

コード結果: バナーコード結果

関連情報