script bash, saída de eco na caixa

5

Eu criei essa função, que gera saída abaixo no terminal, mas essa função parece complexa, então eu postei aqui para qualquer melhoria ou para a mesma solução alternativa.

#!/bin/bashfunctionbox_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 3[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 $@
    
por Rahul Patil 30.03.2013 / 16:08

3 respostas

13

Como seu shebang e sintaxe indicam bash não suportáveis, eu prefiro assim:

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

Claro, você pode otimizá-lo, se desejar.

Atualizar conforme solicitado no comentário, para lidar com texto multilinha também.

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
}

Chame-o com vários parâmetros, como box_out 'first line' 'more line' 'even more line' .

    
por 30.03.2013 / 16:35
3

Assim, minha solução não é bastante igual à sua, mas, estritamente falando, ela imprime uma caixa ao redor do texto, e a implementação é um pouco mais simples, então pensei em compartilhar.

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

E aqui está em ação:

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

Apenas texto simples, sem cores ansiosas ou qualquer coisa.

    
por 18.12.2015 / 02:28
3

Caixas!

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

Como boxes requer que o texto seja enviado para ele como um arquivo, recomendo usar a sintaxe no exemplo acima, em que o texto é canalizado para boxes a echo .

"Por que boxes ?"

Usar é fácil. Basta dizer qual projeto de borda você deseja usar e como deseja que ele apareça e pronto.

Claro, se você quer ser criativo, pode criar seus próprios designs. É muito fácil e divertido de fazer. A única desvantagem de usar boxes é que eu não descobri como centrar uma caixa gerada com boxes para alinhar o centro com a tela, embora haja um corte bash para isso

"E a cor?"

A pergunta original demonstrou o uso de códigos de cores. Então, parece certo mostrar como o boxes lidaria com isso.

Enquanto tput é popular, eu me considero uma pessoa de Bash da velha escola e ainda gosto de usar os comandos de escape. Tenho certeza de que há algumas pessoas aqui no StackExchange que argumentam contra isso, mas para cada uma delas. Independentemente disso, estou disposto a deixar de lado minha preferência pessoal de fazer isso para incluir outro exemplo fazendo a tput way.

Naturalmente, acho que o primeiro passo é definir a cor do texto interno. Então vamos fazer isso primeiro.

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

Se isso estivesse no terminal, Love Unix & Linux seria azul ... no entanto, como você pode ver, boxes não lidou bem com isso. Então, o que foi errado?

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

Uma inspeção mais detalhada mostrando os caracteres ocultos com cat -A mostra que boxes assumiu o tamanho da caixa para incluir o tamanho do texto E os caracteres de escape.

Deve-se notar, no entanto, que se você usar um programa como lolcat fora de boxes , a saída é semelhante a esta

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

mas com a caixa e o texto nas cores do arco-íris.

Ainda bem que eu não fiz os meus próprios designs de borda que incluíam códigos de cores, já que imagino que os designs das bordas seriam passíveis de cair pelos mesmos problemas.

Texto de centralização, arte ASCII e BOXES !!!

A outra falha boxes é que, se você souber como usar o Bash para centralizar o texto no terminal, boxes ainda alinhará a caixa à esquerda da tela. Descobri isso.

Quando você deseja centralizar o texto que não está em uma caixa, basta usar

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

E use isso para centralizar uma única linha de texto.

center 'Love Unix & Linux'

Para o ascii-art em que várias linhas são usadas e devem ser fixadas no local, existe essa opção.

# 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"

Mas se você gosta de usar coisas como figlet , não precisa usar essas funções, pois a opção -c fornece uma opção para centralizar.

$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'

Para boxes , fazemos algo semelhante a draw_banner() , mas precisamos canalizar os dados!

# 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

Questões pendentes

Corrigir esses dois problemas no problema de caractere UTF / ANSI não apenas tornaria boxes uma solução melhor para encapsular texto em uma caixa ASCII, mas também permitir uma alternativa criativa que pudesse ser chamada em vez de caixas de codificação manual.

    
por 23.08.2018 / 17:34