我有一个制表符分隔的文本文件,我将其发送到
column
以“漂亮地打印”表格。
原文件:
1<TAB>blablablabla<TAB>aaaa bbb ccc
2<TAB>blabla<TAB>xxxxxx
34<TAB>okokokok<TAB>zzz yyy
使用
column -s$'\t' -t <original file>
,我明白了
1 blablablabla aaaa bbb xxx
2 blabla xxxxxx
34 okokokok zzz yyy
如所愿。现在我想为列添加颜色。我尝试在原始文件中的每个制表符分隔字段周围添加转义码。
column
成功进行彩色打印,但列不再对齐。相反,它只是逐字打印 TAB 分隔符。
问题是:如何才能使列对齐,而且具有独特的颜色?
我想到了两种方法来实现这一目标:
column
参数以使对齐方式与颜色代码配合使用作为参考,这是我要传递给
column
:
请注意,字段确实是用制表符分隔的。我已经用
od
确认了这一点。
编辑:
着色似乎没有问题。我已经有了上面显示的颜色代码有效的文件。问题是,一旦我发送带有转义码的输入,
column
就不会对齐。我正在考虑将字段
without颜色代码传递给
column
,然后在每个字段之间复制确切数量的空格 column
输出,并在漂亮的打印方案中使用它。awk
进行着色(也可以使用
sed
):awk '{printf "\033[1;32m%s\t\033[00m\033[1;33m%s\t\033[00m\033[1;34m%s\033[00m\n", $1, $2, $3;}' a.txt
并将其通过管道连接到
column
进行对齐:
... | column -s$'\t' -t
输出:
#!/bin/bash
which sed >> /dev/null || exit 1
version=1.0b
editor="Norman Geist"
last="04 Jul 2016"
# NOTE: Brilliant pipeable tool to format input text into a table by
# NOTE: an configurable seperation string, similar to column
# NOTE: from util-linux, but we are smart enough to ignore
# NOTE: ANSI escape codes in our column width computation
# NOTE: means we handle colors properly ;-)
# BUG : none
addspace=1
seperator=$(echo -e " ")
columnW=()
columnT=()
while getopts "s:hp:v" opt; do
case $opt in
s ) seperator=$OPTARG;;
p ) addspace=$OPTARG;;
v ) echo "Version $version last edited by $editor ($last)"; exit 0;;
h ) echo "column2 [-s seperator] [-p padding] [-v]"; exit 0;;
* ) echo "Unknow comandline switch \"$opt\""; exit 1
esac
done
shift $(($OPTIND-1))
if [ ${#seperator} -lt 1 ]; then
echo "Error) Please enter valid seperation string!"
exit 1
fi
if [ ${#addspace} -lt 1 ]; then
echo "Error) Please enter number of addional padding spaces!"
exit 1
fi
#args: string
function trimANSI()
{
TRIM=$1
TRIM=$(sed 's/\x1b\[[0-9;]*m//g' <<< $TRIM); #trim color codes
TRIM=$(sed 's/\x1b(B//g' <<< $TRIM); #trim sgr0 directive
echo $TRIM
}
#args: len
function pad()
{
for ((i=0; i<$1; i++))
do
echo -n " "
done
}
#read and measure cols
while read ROW
do
while IFS=$seperator read -ra COLS; do
ITEMC=0
for ITEM in "${COLS[@]}"; do
SITEM=$(trimANSI "$ITEM"); #quotes matter O_o
[ ${#columnW[$ITEMC]} -gt 0 ] || columnW[$ITEMC]=0
[ ${columnW[$ITEMC]} -lt ${#SITEM} ] && columnW[$ITEMC]=${#SITEM}
((ITEMC++))
done
columnT[${#columnT[@]}]="$ROW"
done <<< "$ROW"
done
#print formatted output
for ROW in "${columnT[@]}"
do
while IFS=$seperator read -ra COLS; do
ITEMC=0
for ITEM in "${COLS[@]}"; do
WIDTH=$(( ${columnW[$ITEMC]} + $addspace ))
SITEM=$(trimANSI "$ITEM"); #quotes matter O_o
PAD=$(($WIDTH-${#SITEM}))
if [ $ITEMC -ne 0 ]; then
pad $PAD
fi
echo -n "$ITEM"
if [ $ITEMC -eq 0 ]; then
pad $PAD
fi
((ITEMC++))
done
done <<< "$ROW"
echo ""
done
使用示例:
bold=$(tput bold)
normal=$(tput sgr0)
green=$(tput setaf 2)
column2 -s § << END
${bold}First Name§Last Name§City${normal}
${green}John§Wick${normal}§New York
${green}Max§Pattern${normal}§Denver
END
输出示例:
printf
来格式化输出的解决方案:
while IFS=$'\t' read -r c1 c2 c3; do
tput setaf 1; printf '%-10s' "$c1"
tput setaf 2; printf '%-30s' "$c2"
tput setaf 3; printf '%-30s' "$c3"
tput sgr0; echo
done < file
,但是对于我所需要的来说太慢了...所以我编写了我自己版本的他的脚本,这次是用Perl(stdin循环和格式化)+Bash(仅用于演示/帮助)。 您可以在此处找到
完整代码以及如何使用它的说明。 它综合了:
类似 Bash
column
相同参数,如
-t
、-s
、-o
)详尽的 column_ansi --help
或 column_ansi -h
可选择awk
生成的彩色输出(超过
300行)格式化为一个漂亮的表格。 我首先想到使用
column
,但我发现它没有考虑 ANSI 字符,因为输出结果会是未对齐。 在 Google 上搜索了一下后,我发现了 @NORMAN GEIST 的有趣答案
,它在删除 ANSI 字符后动态计算输出中每一列的宽度,然后构建了表格。 一切都很好,但是加载时间
太长了(正如有人在评论中指出的那样)... 所以我尝试将
转换@NORMAN GEIST的column2
从
bash
转换为perl
,天哪,如果有变化的话!在我的生产脚本中尝试此版本后,用于显示数据的时间从 30 秒下降到 !! <1s享受吧!
okokokok
为绿色,
blabla
为红色。我可以这样做(想法是在列化之后对列的值进行着色):
GREEN_SED='\\033[0;32m'
RED_SED='\\033[0;31m'
NC_SED='\\033[0m' # No Color
column -s$'\t' -t <original file> | echo -e "$(sed -e "s/okokokok/${GREEN_SED}okokokok${NC_SED}/g" -e "s/blabla/${RED_SED}blabla${NC_SED}/g")"
DATA=$(column -s$'\t' -t <original file>)
GREEN_SED='\\033[0;32m'
RED_SED='\\033[0;31m'
NC_SED='\\033[0m' # No Color
echo -e "$(sed -e "s/okokokok/${GREEN_SED}okokokok${NC_SED}/g" -e "s/blabla/${RED_SED}blabla${NC_SED}/g" <<< "$DATA")"
记下颜色定义值中的附加反斜杠。它是为了 sed 不解释原始的反斜杠而设计的。这是结果:
从
column 的下一个版本 v2.40 开始,将正确处理包含来自 ANSI 转义代码的 Fe 转义序列的文本。 通过此更改,将正确处理使用 ANSI 序列输出文本的程序。