Bash 如何使用awk生成带有彩色输入的固定宽度列?

Bash 如何使用awk生成带有彩色输入的固定宽度列?,bash,awk,ls,Bash,Awk,Ls,我从'ls-l'中获取输出,并将其传递给awk以重新格式化。 这项工作: list=$(ls --color=none -l | tail -n+2) printf '%s' "$list" | awk '{printf "%-40s more stuff\n", $9}' 它会产生如下结果: env_profiles more stuff ls_test.sh more stu

我从'ls-l'中获取输出,并将其传递给awk以重新格式化。 这项工作:

list=$(ls --color=none -l | tail -n+2)
printf '%s' "$list" | awk '{printf "%-40s more stuff\n", $9}'
它会产生如下结果:

env_profiles                             more stuff
ls_test.sh                               more stuff
saddfasfasfdfsafasdf                     more stuff
test                                     more stuff
但是使用--color=它总是产生:

env_profiles                 more stuff
ls_test.sh                   more stuff
saddfasfasfdfsafasdf             more stuff
test                             more stuff
                                         more stuff
“env_profiles”是一个目录,“ls_test.sh”是一个可执行文件,因此它们都是彩色的,并以不同的对齐方式结束。还有一条额外的线路

编辑:根据Ed Morton的帖子修改答案。去掉多余的行,处理带有空格的文件名:

ls --color=always -l | tail -n+2 | awk '
{
    $1=$2=$3=$4=$5=$6=$7=$8=""
    field = substr($0,9)
    nameOnly = $0
    gsub(/\x1b[^m]+m/,"",nameOnly)
    if( length(field) - length(nameOnly) >= 0 ) {
        printf "%-*s more stuff\n", 40 + length(field) - length(nameOnly), field
    }
}'
解释
gsub
返回在一行上进行的替换次数。在本例中,我们将转义字符
\x1b
替换为自身,存储它出现的次数

如果没有找到转义序列(
count==0
),我们将添加40个空格作为填充。
如果行上有转义序列(即颜色),我们将添加40个空格的填充,再加上10个空格。当然,
count
已经等于逃逸次数

我发现在我的系统中,如果一行有颜色,它需要多10个空格的填充,加上转义字符的数量来匹配未着色的行。例如:正常填充=40;线路上有3个逃逸序列;填充应为40+10+3=53。这在您的系统上可能不同,可能需要调整数字

最后,我们打印该行,用
count
代替填充。

包含彩色文件名的字段($9)以控制字符开始和结束,以在终端上生成颜色,例如,在这种情况下,
foo
在屏幕上是彩色的,但
bar
不是:

$ cat o1
-rwxr-xr-x  1 emorton Domain Users     21591 Nov 12  2011 foo
-rwxr-xr-x  1 emorton Domain Users     21591 Nov 12  2011 bar

$ cat -v o1
-rwxr-xr-x  1 emorton Domain Users     21591 Nov 12  2011 ^[[01;32mfoo^[[0m
-rwxr-xr-x  1 emorton Domain Users     21591 Nov 12  2011 bar
因此,当您在awk中打印该字段并为其指定N个字符的字段宽度时,产生颜色的字符串将作为宽度的一部分计算,但如果它们是非打印字符串或退格字符串或其他类型的字符串,则最终结果将不会显示它们,并且看起来它使用的空间会更少—字段中不包含这些字符。希望这是有道理的

在我看来,着色字符串总是以字符
\x1b
开始,然后是一些着色指令,以
m
结束,因此请尝试以下操作:

$ awk '{
    nameOnly = $NF
    gsub(/\x1b[^m]+m/,"",nameOnly)
    printf "<%-*s>\n", 10 + length($NF) - length(nameOnly), $NF
}' o1
<foo       >
<bar       >
$awk'{
name only=$NF
gsub(/\x1b[^m]+m/,“”,仅限名称)
printf“\n”,10+长度($NF)-长度(仅限名称),$NF
}“o1

请注意,您使用特定字段的方法仅在文件名中没有空格时有效

彩色输入包含转义序列。因此,它与显示的不同。对我来说不起作用,因为即使未着色的行也有\x1b字符(至少在我的设置中,MinGW/MSYS)
$ awk '{
    nameOnly = $NF
    gsub(/\x1b[^m]+m/,"",nameOnly)
    printf "<%-*s>\n", 10 + length($NF) - length(nameOnly), $NF
}' o1
<foo       >
<bar       >