web-dev-qa-db-ja.com

bashスクリプト、ボックスにエコー出力

端末で以下の出力を生成するこの関数を作成しましたが、この関数は複雑に思われるため、改善または同じ代替ソリューションのためにここに投稿しました。 enter image description here

#!/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 $@
6
Rahul Patil

あなたのシバンと構文が移植できないbashを示しているので、私はそれをこのように好みます:

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

もちろん、必要に応じて最適化できます。

pdateコメントで要求されているとおり、複数行のテキストも処理します。

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'のような複数のパラメーターで呼び出します。

15
manatwork

だから、私の解決策はquiteと同じではありませんが、厳密に言えば、テキストの周りにボックスを印刷し、実装は少し簡単なので、共有したいと思いました。

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

そしてここでそれは動作しています:

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

プレーンテキストだけで、派手なANSIカラーなどはありません。

6
robru

ボックス!

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

boxesではテキストをファイルとして送信する必要があるため、テキストをboxesからechoにパイプする上記の例の構文を使用することをお勧めします。

「なぜboxes?」

使い方は簡単です。使用したいボーダーデザインとその表示方法を伝えれば完了です。

もちろん、クリエイティブになりたい場合は、独自のデザインを作成できます。それは本当に簡単で楽しいことです。 boxesを使用する唯一の欠点は、boxesで生成されたボックスを中央に配置して画面の中央に配置する方法を理解していないことですが、bashハックがあります。

「色は?」

元の質問は、カラーコードの使用を示していました。したがって、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の-​​ boxesoutsideのようなプログラムを使用すると、出力は次のようになります。このような

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

ただし、ボックスとテキストはレインボーカラーで表示されます。

ボーダーのデザインが同じ問題に陥る可能性があると想像するので、カラーコードを含む独自のボーダーデザインをまだ作成していなかったのは良いことです。

中央揃えテキスト、ASCIIアート、およびボックス!!!

boxesのもう1つの欠点は、Bashを使用してテキストを端末の中央に配置する方法を知っている場合でも、boxesがボックスを画面の左側に揃えることです。 理解した。

ボックス内にないテキストを中央揃えにしたい場合は、簡単に使用できます

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

それを使用して、1行のテキストを中央揃えにします。

_center 'Love Unix & Linux'
_

複数の線が使用され、定位置に固定する必要があるASCIIアートの場合、このオプションがあります。

_# 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
JRCharney