如何在 UNIX 中居中对齐列?

如何在 UNIX 中居中对齐列?

我正在尝试使用命令居中对齐列column

输出应如下所示:

temperatures  
    50  
    12  
    89  
    63  

我怎样才能做到这一点?

答案1

我在注意到您想要使用该column命令之前写了这个答案,但如果这不是必需的,您可以使用以下bashshell 脚本将文本居中:

#!/bin/bash
set -e    # exit the script if something goes wrong

width=12
data="temperatures 50 12 89 63"

for word in $data; do
    strlen=$(printf $word | wc -c)
    w=$(( ($width - $strlen)/2 ))
    printf "%${w}s%s\n" "" $word
done

怎么运行的:

  • $width是列宽
  • 循环for打印中的每个单词$data
  • $strlen是当前字的长度,以字节为单位。
  • $w是在单词之前打印的空格数,以使其居中。
  • printf打印$w空格,后跟单词

输出:

temperatures
     50
     12
     89
     63

该脚本仅适用于单字节文本编码。您需要更改该strlen行来处理包含

答案2

给定一些文件,

temps,temperatures,heatness
500,50,50
1212,12,12
899,89,8989
63,6363,63

column命令可以为您提供对齐的列,但没有对它们进行其他特殊调整:

$ column -t -s, file
temps         temperatures  heatness
500           50            50
1212          12            12
899           89            8989
63            6363          63

使用一个小awk脚本,我们可以进行居中:

$ awk -F, -f center-cols.awk file
temps temperatures heatness
 500       50         50
1212       12         12
 899       89        8989
 63       6363        63
$ awk -F, -v OFS='|' -f center-cols.awk file
temps|temperatures|heatness
 500 |     50     |   50
1212 |     12     |   12
 899 |     89     |  8989
 63  |    6363    |   63

center-cols.awk脚本可能看起来像

function center(w, string,         space, before, after) {
    space  = w - length(string)  # number of spaces in total to fill
    before = int(space/2)        # spaces before string
    after  = space - before      # the rest of spaces after
    return sprintf("%*s%s%*s", before, "", string, after, "")
}

FNR == 1 {
    for (i = 1; i <= NF; ++i)
        width[i] = length($i)
}

{
    for (i = 1; i <= NF; ++i)
        $i = center(width[i], $i)

    print
}

该脚本根据每行标题列(第一行)的宽度将数据中的每列居中。这意味着数据长于标题的行仍然会不对齐。此限制简化了脚本的实现(否则必须解析文件两次,一次查找每列的最大列宽,一次重新格式化数据)。

该脚本首先获取每个标题列的宽度并将其保存到width数组中。然后它使用该center函数重写每一列。

center函数接受一个宽度和一个字符串,并返回一个以该宽度为中心的字符串,两侧的空格填充未使用的空间。生成的字符串是sprintf()使用格式说明符写入侧翼空格来构造的%*s。该说明符采用宽度和字符串,我们为它提供计算出的宽度和实际数据开头和后面的空格的空字符串(空字符串将被格式化为给定的宽度)。

一旦行的所有列都被重新格式化,该行就会被打印。


通过解析文件两次,我们可以找到每列的最大宽度。这样我们就不必依赖标题行来定义列的宽度:

function center(w, string,         space, before, after) {
    space  = w - length(string)  # number of spaces in total to fill
    before = int(space/2)        # spaces before string
    after  = space - before      # the rest of spaces after
    return sprintf("%*s%s%*s", before, "", string, after, "")
}

NR == 1 {
    for (i = 1; i <= NF; ++i)
        width[i] = length($i)
    next
}

FNR == NR {
    for (i = 1; i <= NF; ++i)
        if (width[i] < length($i))
            width[i] = length($i)
    next
}

{
    for (i = 1; i <= NF; ++i)
        $i = center(width[i], $i)

    print
}

在具有短列标题的文件上运行此命令:

$ awk -F, -v OFS='|' -f center-cols.awk file file
 t  | a  | b
500 | 50 | 50
1212| 12 | 12
899 | 89 |8989
 63 |6363| 63

请注意,我们需要在命令行上给出两次文件名。

相关内容