我正在尝试使用命令居中对齐列column
。
输出应如下所示:
temperatures
50
12
89
63
我怎样才能做到这一点?
答案1
我在注意到您想要使用该column
命令之前写了这个答案,但如果这不是必需的,您可以使用以下bash
shell 脚本将文本居中:
#!/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
请注意,我们需要在命令行上给出两次文件名。