【问题标题】:I would like to concatenate two figlet outputs (with different colors)我想连接两个 figlet 输出(具有不同的颜色)
【发布时间】:2022-01-23 01:39:16
【问题描述】:

目前我有这种输出格式:

{ echo "$(figlet buddhi)"; echo "$(figlet lw)"; }
 _               _     _ _     _
| |__  _   _  __| | __| | |__ (_)
| '_ \| | | |/ _` |/ _` | '_ \| |
| |_) | |_| | (_| | (_| | | | | |
|_.__/ \__,_|\__,_|\__,_|_| |_|_|

 _
| |_      __
| \ \ /\ / /
| |\ V  V /
|_| \_/\_/


我想要这种输出格式:

figlet buddhi lw
 _               _     _ _     _   _
| |__  _   _  __| | __| | |__ (_) | |_      __
| '_ \| | | |/ _` |/ _` | '_ \| | | \ \ /\ / /
| |_) | |_| | (_| | (_| | | | | | | |\ V  V /
|_.__/ \__,_|\__,_|\__,_|_| |_|_| |_| \_/\_/

原因是:我想用不同的颜色为每个名字(buddhi,lw)着色。但是,保留连续字符串的格式,或者最大空间分隔,如上。

例子:

 #COMMANDS CREATED INSIDE /ETC/BASH.BASHRC FILE
 # USING ANSI COLORS
 RED="\e[31m"
 ORANGE="\e[33m"
 BLUE="\e[94m"
 GREEN="\e[92m"
 STOP="\e[0m"


 printf "${GREEN}"
 printf "=================================\n"
 printf "${ORANGE}"
 figlet -f standard "Buddhi"
 printf "${BLUE}"
 figlet -f  small "LW"
 printf "${GREEN}"
 printf "=================================\n"
 printf "${STOP}"

【问题讨论】:

    标签: bash shell figlet


    【解决方案1】:

    使用坐标

    #!/bin/bash
    
    RED='\e[31m'
    GRN='\e[32m'
    
    XY(){ printf "\e[$2;${1}H$3"; }
    
    mapfile -t frst < <(figlet -f standard "Buddhi")
    mapfile -t scnd < <(figlet -f small    "LW")
    
    XY 1 1 "$GRN==============================================="; y=2
    for line in "${frst[@]}"; { XY 0  $y "$RED$line"; ((y++)); }; y=2
    for line in "${scnd[@]}"; { XY 35 $y "$GRN$line"; ((y++)); }
    XY 1 8 "$GRN==============================================="
    

    更多示例hereherehere

    【讨论】:

      【解决方案2】:

      代替figlet,我将使用以下内容作为我的输入:

      $ cat buddhi
       _               _     _ _     _
      | |__  _   _  __| | __| | |__ (_)
      | '_ \| | | |/ _` |/ _` | '_ \| |
      | |_) | |_| | (_| | (_| | | | | |
      |_.__/ \__,_|\__,_|\__,_|_| |_|_|
      
      $ cat lw
       _
      | |_      __
      | \ \ /\ / /
      | |\ V  V /
      |_| \_/\_/
      

      假设figlet 为每个输入字符串生成相同数量的输出行,我们可以使用paste@ 作为分隔符)和while/read 循环来生成所需的输出:

      printf "${GREEN}"
      printf "============================\n"
      
      maxwidth=$(awk '{max=length($0) > max ? length($0) : max}END{print max}' buddhi)
      
      while IFS='@' read -r col1 col2
      do
          printf "${ORANGE}%-*s ${BLUE}%s\n" "${maxwidth}" "${col1}" "${col2}"
      done < <(paste -d"@" buddhi lw)
      
      printf "${GREEN}"
      printf "============================\n"
      

      这会生成:


      扩展到 3 个输入流:

      printf "${GREEN}"
      printf "============================\n"
      
      max1=$(awk '{max=length($0) > max ? length($0) : max}END{print max}' buddhi)
      max2=$(awk '{max=length($0) > max ? length($0) : max}END{print max}' lw)
      
      while IFS='@' read -r col1 col2 col3
      do
          printf "${ORANGE}%-*s ${BLUE}%-*s ${RED}%s\n" "${max1}" "${col1}" "${max2}" "${col2}" "${col3}"
      done < <(paste -d"@" buddhi lw buddhi)
      
      printf "${GREEN}"
      printf "============================\n"
      

      这会生成:

      【讨论】:

        【解决方案3】:

        发明 shell 的人还发明了 awk 让 shell 调用来操作文本。这些转义序列不会在我的终端上改变颜色,它们只是按原样显示(幸运的是,你可以看到脚本将它们放在哪里):

        $ cat tst.sh
        #!/usr/bin/env bash
        
        awk '
            BEGIN {
                red =    "\\e[31m"
                orange = "\\e[33m"
                blue =   "\\e[94m"
                green =  "\\e[92m"
                stop =   "\\e[0m"
            }
            {
                val[(NR==FNR),FNR] = $0
            }
            NR == FNR {
                wid = length($0)
                maxWid = ( wid > maxWid ? wid : maxWid )
            }
            END {
                for ( lineNr=1; lineNr<=FNR; lineNr++ ) {
                    printf "%s%-*s%s%s%s\n", orange, maxWid, val[1,lineNr], blue, val[0,lineNr], stop
                }
            }
        ' <(cat Buddhi) <(cat LW)
        

        $ ./tst.sh
        \e[33m _               _     _ _     _ \e[94m _\e[0m
        \e[33m| |__  _   _  __| | __| | |__ (_)\e[94m| |_      __\e[0m
        \e[33m| '_ \| | | |/ _` |/ _` | '_ \| |\e[94m| \ \ /\ / /\e[0m
        \e[33m| |_) | |_| | (_| | (_| | | | | |\e[94m| |\ V  V /\e[0m
        \e[33m|_.__/ \__,_|\__,_|\__,_|_| |_|_|\e[94m|_| \_/\_/\e[0m
        

        因为我没有figlet,所以我在这些文件上运行了上面的代码:

        $ head Buddhi LW
        ==> Buddhi <==
         _               _     _ _     _
        | |__  _   _  __| | __| | |__ (_)
        | '_ \| | | |/ _` |/ _` | '_ \| |
        | |_) | |_| | (_| | (_| | | | | |
        |_.__/ \__,_|\__,_|\__,_|_| |_|_|
        
        ==> LW <==
         _
        | |_      __
        | \ \ /\ / /
        | |\ V  V /
        |_| \_/\_/
        

        只需将脚本的最后一行更改为:

        ' <(cat Buddhi) <(cat LW)
        

        ' <(figlet Buddhi) <(figlet LW)
        

        使用实际的figlet 输出。

        以上假设您只有 2 个 figlet 输出字符串要连接,并且两组输出的长度相同,如果其中任何一个假设错误,则很容易调整。

        【讨论】:

        • @Ivan 让我知道你觉得难以理解的地方,我很乐意解释。对我来说,它似乎比目前接受的答案或大多数(如果不是全部)其他答案更容易理解(我认为,所有这些都属于“初学者很难”类别!)而且它是最有效和最可靠的答案,并且最便携,因为如果您只需通过创建临时文件替换那些 &lt;(..) 构造,它就可以在任何 shell 中使用任何 awk。
        • @Ivan FNR 是读取当前文件时的当前行号,NR 是所有输入文件的行号。 NR==FNR 正在测试这是第一个文件还是第二个文件,并将其用作数组 va[] 的复合索引的第一部分只是为两个输入文件逐行填充 val[] 的一种方法,因此您获取val[0,1]保留第一个文件读取的第1行和val[1,1]保留第2个文件读取的第1行。
        • 在 awk 中编写 val[(NR==FNR),FNR] = $0 就像在 shell 中编写 val[((NR==FNR))","$FNR]="$line" 作为代码 sn-p 的一部分,如 declare -A val; NR=0; FNR=0; while IFS= read -r line; do (( NR++ )); (( FNR++ )); val[((NR==FNR))","$FNR]="$line"; done &lt; file1; FNR=0; while IFS= read -r line; do (( NR++ )); (( FNR++ )); val[((NR==FNR))","$FNR]="$line"; done &lt; file2 ,其中其余代码是 awk 始终为您所做的一部分阅读输入。
        • awk 真是强大的东西,谢谢你的解释。
        【解决方案4】:

        如果您需要更短的版本:

        printf "$GREEN=================================\n"
        { figlet Buddhi; echo 'EOF'; figlet LW; } | awk 'NF==1&&$1=="EOF" {noskip=1; next; } noskip==0 { f[++c]=$0; next; } { printf "%s%s%s%s\n","'"$ORANGE"'",f[++k],"'"$BLUE"'",$0;}'
        printf "$GREEN=================================\n"
        tput sgr0
        

        我建议使用 tput 设置颜色,因为不是每个终端都会知道您的转义序列

        【讨论】:

        • 我收到错误:awk: cmd. line:1: warning: escape sequence `\e' treated as plain `e'
        • 不要让 shell 变量扩展成为 awk 脚本主体的一部分,请参阅 how-do-i-use-shell-variables-in-an-awk-script
        • 埃德 - 你是对的。这只是一个快速破解。在我的终端上它可以工作:-)
        【解决方案5】:

        将每个单词的行存储在数组中,逐行输出两个数组。由于“Buddhi”的第一行似乎短了一个字符,所以我将第一个单词的最长行长度存储在一个变量中,并使用%-s 格式填充每一行。

        #! /bin/bash
        RED="\e[31m"
        ORANGE="\e[33m"
        BLUE="\e[94m"
        GREEN="\e[92m"
        STOP="\e[0m"
        
        mapfile -t left  < <(figlet -f standard "Buddhi")
        mapfile -t right < <(figlet -f small    "LW")
        
        maxlength=0
        for line in "${left[@]}" ; do
            if (( ${#line} > maxlength )) ; then
                maxlength=${#line}
            fi
        done
        
        printf "${GREEN}"
        printf "=================================\n"
        
        for ((i=0; i<=${#left[@]}; ++i)) ; do
            printf "${ORANGE}%-${maxlength}s ${GREEN}%s\n" "${left[i]}" "${right[i]}"
        done
        
        printf "${GREEN}"
        printf "=================================\n"
        printf "${STOP}"
        

        【讨论】:

        • 哇,太快了。谢谢你。我会仔细研究你的程序。
        猜你喜欢
        • 2018-08-25
        • 2018-10-02
        • 2011-04-07
        • 1970-01-01
        • 1970-01-01
        • 2014-07-17
        • 2012-01-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多