使用 tput 颜色似乎会干扰列的输出。为什么会发生这种情况,更重要的是有解决办法吗?
$ {
echo "$(tput bold)foo$(tput sgr0)" "$(tput bold)bar$(tput sgr0)"
echo bar foo
} | column -t
foo bar
bar foo
我在 macos 和 ubuntu 20.04 上重现了这个问题,尽管它们似乎都使用 BSD 列
答案1
您可以通过管道cat -v
查看该文件流的所有字符。column
使用它们计算宽度:
^[[1mfoo^[(B^[[m ^[[1mbar^[(B^[[m
bar foo
正确的方法是将任何内容创建与任何格式分开(如 MVC 模型)。请注意,column
添加空格以生成类似制表符的输出,因此它会修改内容。同时tput
向终端添加指令。通过分离这些任务,我们能够将输出保存到文件中,或者从我们的格式化函数传递它以将其发送到控制台,或者将其格式化为其他目的地。
但这也是一个很好的练习awk
,可以实现column -t
从宽度计算中排除某些字符。我下面使用的正则表达式捕获了很多tput
东西,但我几乎可以肯定不是全部。
$ cat tst.awk
BEGIN {
OFS = " "
}
{
nr = NR
for (i=1;i<=NF;i++) {
f[NR,i] = $i
gsub(/\x1B[^[:alpha:]]+[[:alpha:]]/,"",$i)
if (length($i) > col[i]) col[i] = length($i)
}
}
END {
for (i=1;i<=nr;i++) {
for (j=1;j<=length(col);j++) {
printf "%-"col[j]"s%s", f[i,j], (j==length(col)? ORS : OFS)
}
}
}
然后将第一个输出通过管道传输到awk -f tst.awk
答案2
${ echo -e "$(tput 粗体)foo$(tput sgr0)" "$(tput 粗体)bar$(tput sgr0) baz"; 回声酒吧富; } |cat -v ^[[1mfoo^[(B^[[m ^[[1mbar^[(B^[[m baz) 富酒吧
问题在于tput sgr0
,正如您所知,默认情况下tputs
使用基于从环境变量获取的终端类型的转义代码TERM
。
如果你这样做:
infocmp -1 |grep -E 'bold|sgr0'
bold=\E[1m,
sgr0=\E(B\E[m,
你会看到什么大胆的和sgr0代码是(那些是非 ANSI 转义值),正如您在cat -v
转换为^[[1m
fortputs bold
和^[(B^[[m
for后的输出中看到的那样sgr0
,column
命令执行相同的操作并解析为 ANSI 转义类型代码,但当存在(B
并保留时会失败^[(B^[[m
,然后就不会在 ANSI 转义中被识别并导致最终输出未按预期正确地按列输出。
如果你这样做:
infocmp -1 -T ansi |grep -E 'bold|sgr0'
bold=\E[1m,
sgr0=\E[0;10m,
您将找到每个等效的 ANSI 转义码;所以你有两个选择来解决它:
替换
tputs
为上面的 ANSI 转义码{ echo -e "\033[1mfoo\033[0;10m" "\033[1mbar\033[0;10m baz"; echo bar foo; } |column -t
将终端类型传递给
tputs
:{ echo -e "$(tput bold)foo$(tput -T ansi sgr0)" "$(tput bold)bar$(tput -T ansi sgr0) baz"; echo bar foo; } |column -t
答案3
column
我正在运行 Ubuntu 18.04,并对未按预期运行的行为感到困惑。正如其他人所建议的,问题在于该仓库包含一件古董。
我发现获得现代版本的唯一方法是从util-linux
回购协议。
很难弄清楚这一点,因为-V
尚未添加获取版本!可能有一种更优雅的方式,但我通过调用man column
底部的日期“2004 年 7 月 29 日”来推断出大致的版本。比较2004 年联机帮助页到2019 年联机帮助页。虽然前者仅描述四选项,后者几乎有两打!
我还可以说,在 MacOS Catalina 上我得到了完全相同的结果。我无法找到brew
包含更新版本的软件包,column
但它可能隐藏在某个地方。
如果您无法访问现代版本,您应该确保检查与现有版本相对应的手册页,否则事情会令人沮丧!