Bash 如何使用awk生成带有彩色输入的固定宽度列?
我从'ls-l'中获取输出,并将其传递给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
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 >