修剪线条很容易:
print -l $array | cut -$COLUMNS
...但是如果数组的线是彩色的,则剪切是错误的,因为颜色代码计入线的宽度,因此实际上彩色线被剪切得太短。有一些现成的修正吗?粗略地说,如果我一行中有一个彩色单词,我会这样做:
... $(( COLUMNS + 17 ))
……但如果有更多的彩色单词,那当然是错误的。
答案1
您必须以某种方式计算转义码中使用的字符数,然后将它们添加到 $COLUMNS 中。
这是获取计数的方法:
echo -E $mystring | grep -Eoz '\\e\[[0-9;]+m' | sed -e 's/\x00//g' | wc -m
echo
args:用于-E
保持颜色代码不变,以便我们可以 grep 它们grep
args:用于-E
匹配扩展正则表达式,用于-o
仅返回行的匹配部分,用于-z
替换换行符\x00
- 然后我们用
sed
它来剥离\x00
字节,最后 wc
返回字符数
好的,让我们在一些示例字符串上测试一下:
mystring='\e[1;31;3mThis is red text, and \e[1;32mthis is green text \e[0m'
echo -E "$mystring" | grep -Eoz '\\e\[[0-9;]+m' | sed -e 's/\x00//g' | wc -m
echo -e "$mystring"
看起来不错,打印 23,然后应用着色的字符串。现在构建整个东西:
cols=20
mystring='\e[1;31;3mThis is red text, and \e[1;32mthis is green text \e[0m'
# strip the reset escape code from end of the line so it doesn't get counted
mystring=$(echo -E $mystring | sed -e 's/\\e\[0m$//g')
# count the escape codes
countesc=$(echo -E "$mystring" | grep -Eoz '\\e\[[0-9;]+m' | sed -e 's/\x00//g' | wc -m)
# cut the line while accounting for escape codes, and add back the reset escape code to the end
echo -e $(echo -E "$mystring" | cut -b -$((cols+countesc)))"\e[0m"
如果您在最后一个颜色代码之后进行剪切,则此方法有效。必须构建更复杂的东西来考虑颜色代码的位置。
答案2
解决方案可能是使用 gawk(gnu awk,或任何知道如何在拆分时将分隔符保留在数组中的新 awk)来:拆分“转义码”,并计算需要显示的实际字符。
假设:除了转义码之外,您只有“常规可打印字符”。如果您有更复杂的输入,则需要考虑它(修改 $color_escape_codes 值以添加:“|some_other_noncounted_char(s)”)
len=123 # or $COLUMNS, or whatever you want it to be: the nb of chars to cut at
color_escape_codes="$( printf '\033[' )[0-9;]+m"
gawk -F"${color_escape_codes}" -v len=$len '
{
nf=split( $0, a, FS, seps )
cur=0
for( i=1; i<=nf; i++ ) {
cur=cur + length( a[i] )
if( cur<=len ) {
printf( "%s%s", a[i], seps[i] )
if( (cur==len) || (i==nf) ) {
print ""
break
}
} else {
printf( "%s\n", substr( a[i], 1, (len-(cur-length(a[i]))) ) )
break
}
}
}'
答案3
这就是我最终的做法。相当简单的东西:
让 'var' 是一个变量,其中包含一些颜色代码:
lenvar=$#var
stripped=$( echo $var | stripcolors )
lenstripped=$#stripped
(( difference = lenvar - lenstripped ))
((correctedwidth = COLUMNS + difference))
echo $var | cut -c -$correctedwidth
...神奇成分:
stripcolors is an alias for sed "s/\x1B\[\([0-9]\{1,2\}\(;[0-9]\{1,2\}\)\?\)\?[mGK]//g"