Bash:在同一列内包裹长行

时间:2016-05-02 10:08:19

标签: bash formatting

我想创建一个包含两列的表。第一列包含键名,第二列包含值。该值可以是通常在终端中产生多行的文本。

使用printfcolumn,我可以轻松获得以下输出:

<----- Terminal Length ------>
key1     This is the value for
key1 with a very long text. 
...

但我想将值显示在同一列中,如下所示:

<----- Terminal Length ------>
key1     This is the value for
         key1 with a very long
         text.
...

如何在同一列中包含长行?

4 个答案:

答案 0 :(得分:2)

基于andlrc评论的解决方案:

columnize2 () { 
    indent=$1; 
    collen=$(($(tput cols)-indent)); 
    keyname="$2"; 
    value=$3; 
    while [ -n "$value" ] ; do 
        printf "%-10s %-${indent}s\n" "$keyname" "${value:0:$collen}";  
        keyname="";
        value=${value:$collen}; 
    done
}

longvalue=---------------------------------------------------------------------xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
columnize2 30 key1 $longvalue
key1       --------------------------------------------------
           -------------------xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
           xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxzz

tput cols返回终端窗口中每行的字符数。我们使用它来确定每行可以打印的值的字符数(collen)。如果它不适合一行,则其余行打印在以下行上。 print语句中的%-10s用于分配10个字符以显示键名(长键处理不好)。 %-${indent}s用于通过#indent字符缩进值。 仅打印适合一行的值的多个字符:${value:0:$collen}并从值value=${value:$collen}中删除已打印的字符 对于以下行,我们不打印键名(通过将其设置为空字符串)。

答案 1 :(得分:0)

我正在写屏幕和文件,并且难以维护标签。我切换到间距因为它在屏幕/文件和linux / windows之间完全相同。下面是一些用空格填充字段的代码,以确保下一个字段与每个列项目的距离相等。如果你想填充开头,只需将空格移动到变量的开头而不是在&#34; sHeading =&#34;之后。线。如果你愿意,也可以使用Tab键进行相同操作。

\d

答案 2 :(得分:0)

实际上,util-linux的“ column”命令可以做到这一点。它非常通用。

#!/bin/bash

cat <<- EOF | column --separator '|' \
                     --table \
                     --output-width 30 \
                     --table-noheadings \
                     --table-columns C1,C2 \
                     --table-wrap C2
key1|Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
key2|blahhhhhhhhhhhhhhhhhhhhhhhhhhhhzzz
EOF

这给出了:

key1  Lorem ipsum dolor sit am
      et, consectetur adipisci
      ng elit, sed do eiusmod
      tempor incididunt ut lab
      ore et dolore magna aliq
      ua.
key2  blahhhhhhhhhhhhhhhhhhhhh
      hhhhhhhzzz

--output-width:给出所需的大小(可以使用如上所述的“ tput cols”)

--table-columns C1,C2:为要与其他选项结合使用的列命名

--table-wrap C2:包装第2列

列版本:

# column -V
column from util-linux 2.33.1

答案 3 :(得分:0)

我最近在想同样的问题。我编写了一个名为printf-wrap的小脚本来实现此功能,其灵感来自@phobic。之所以必要,是因为用户工作区上的column版本可能没有包装功能,并且他/她也没有被授权安装或更新任何软件包。 (是的,用户是我...)

printf-wrap接受与printf相同的相同输入参数,并巧妙地包装 每列 。然后,您可以使用tput将其调整为终端宽度。

# printf-wrap
# Description:  Printf with smart word wrapping for every columns.
# Usage:        print-wrap "<format>" "<text>" "<text>" ...
function printf-wrap {
    # help info
    help_message="Usage: print-column-wrap \"<format>\" \"<text>\" \"<text>\" ..."
    if [[ "$1" =~ ^(-|--)?(h|help)$ ]] ; then echo "$help_message" ; return 0 ; fi 
    # parse argument
    format="$1"
    width=( $( echo "$format" | sed -r 's/%%|\\%//g' | sed -r 's/%/\n%/g' | sed -n -r 's/^%[^1-9]*([0-9]+).*/\1/p' ) )
    shift
    text=( "$@" )
    error_message="Error: number of input text fields (${#text[@]}) MUST NOT EXCEED number of columns specified (${#width[@]}) !"
    if (( ${#text[@]} > ${#width[@]} )) ; then echo "$error_message" ; return 1 ; fi
    # printing
    while [ -n "$( echo "${text[@]}" | sed -r 's/\s+//g' )" ] ; do
        text_cut=()
        width_cut=()
        for i in ${!text[@]} ; do
            text[$i]="$( echo "${text[$i]}" | sed -r 's/^\s+//' )"
            if [[ "${text[$i]:${width[$i]}-1:2}" =~ [a-zA-Z0-9_]{2} ]] ; then
                text_cut[$i]="$( echo "${text[$i]:0:${width[$i]}}" | sed -r 's/\w+$//' )"
            else
                text_cut[$i]="${text[$i]:0:${width[$i]}}"
            fi
                width_cut[$i]=${#text_cut[$i]}
                text[$i]="${text[$i]:${width_cut[$i]}}"
        done
        printf "$format" "${text_cut[@]}"
    done
}

输出看起来如下。

$ printf-wrap "%-10s %-$(( $(tput cols) - 11 ))s\n" "key1" "This is the value for key1 with a very long text"
============ Terminal Width ============
key1       This is the value for key1   
           with a very long text

希望这可以帮助任何人。 :)