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

时间:2014-05-04 15:56:18

标签: 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 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
    }
}'

2 个答案:

答案 0 :(得分:0)

ls --color=always -l | tail -n+2 | awk '{count = gsub(/\x1b/, "\x1b"); if (count == 0) count += 40; else count += 50; printf "%-"count"s more stuff\n", $9}'

说明

gsub返回一行上的替换次数。在这种情况下,我们用自身替换转义字符\x1b,存储它出现的次数。

如果找不到转义序列(count == 0),我们会添加40个填充空格 如果行上的转义序列(即颜色),我们会添加40个填充空格加上另外10个空格。当然,count已经等于转义次数。

我发现在我的系统上,如果一行有颜色,则需要10个以上的填充空间,以及与未着色的行匹配的转义字符数。例如:普通填充= 40;线路上有3个逃生序列;填充应该是40 + 10 + 3 = 53.这可能在您的系统上有所不同,可能需要调整数字。

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

答案 1 :(得分:0)

包含彩色文件名的字段($ 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       >

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