상자!

상자!

예제 이미지에 표시된 출력을 인쇄하는 이 함수를 만들었습니다. 하지만 이 기능의 구현은 너무 복잡해 보입니다.

이를 개선하거나 대체 솔루션을 구현할 수 있는 방법이 있습니까?

다음은 문자열 매개변수 "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텍스트를 파일로 보내야 하므로 텍스트 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 아트 및 상자! ! !

또 다른 결점 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

코드 결과: 배너 코드 결과

관련 정보