漂亮打印列中的颜色转义代码

问题描述 投票:0回答:6

我有一个制表符分隔的文本文件,我将其发送到

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 分隔符。

问题是:如何才能使列对齐,而且具有独特的颜色?

我想到了两种方法来实现这一目标:

  1. 调整
    column
    参数以使对齐方式与颜色代码配合使用
  2. 将列的输出重定向到另一个文件,并对前两个空格分隔的字段执行搜索+替换(前两列保证不包含空格;第三列很可能包含空格,但没有制表符字符)
  3. 问题是,我不知道如何做这两个...

作为参考,这是我要传递给

column


Original file with color codes请注意,字段确实是用制表符分隔的。我已经用

od

确认了这一点。


编辑:

着色似乎没有问题。我已经有了上面显示的颜色代码有效的文件。问题是,一旦我发送带有转义码的输入,

column

就不会对齐。我正在考虑将字段

without
颜色代码传递给 column,然后在每个字段之间复制确切数量的空格
column
输出,并在漂亮的打印方案中使用它。
    

bash unix escaping multiple-columns
6个回答
9
投票
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

输出:

output


9
投票

#!/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

输出示例:

enter image description here


3
投票
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

enter image description here


2
投票

TL;博士

我真的很喜欢

@NORMAN GEIST的答案

,但是对于我所需要的来说太慢了...所以我编写了我自己版本的他的脚本,这次是用Perl(stdin循环和格式化)+Bash(仅用于演示/帮助)。 您可以在此处找到

完整代码以及如何使用它的说明。 它综合了:

类似 Bash
    column
  • 的命令界面(
    相同参数
    ,如 -t
    -s
    -o
    详尽的 
  • 帮助
  • ,带有 column_ansi --help
    column_ansi -h
    可选择
  • 水平居中
  • 实际的“核心”代码可以分解为
仅 Perl 部分

背景和差异

我需要将

很长

awk生成的彩色输出(超过

300行
)格式化为一个漂亮的表格。 我首先想到使用 column,但我发现它没有考虑 ANSI 字符,因为输出结果会是
未对齐
在 Google 上搜索了一下后,我发现了

@NORMAN GEIST 的有趣答案

,它在删除 ANSI 字符后动态计算输出中每一列的宽度,然后构建了表格。 一切都很好,但是加载时间

太长了

(正如有人在评论中指出的那样)... 所以我尝试将

转换

@NORMAN GEIST的column2

bash
转换为
perl
,天哪,如果有变化的话!
在我的生产脚本中尝试此版本后,用于显示数据的时间

从 30 秒下降到

!! <1s享受吧!


1
投票
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 不解释原始的反斜杠而设计的。
这是结果:


0
投票
/

column 的下一个版本 v2.40 开始,将正确处理包含来自 ANSI 转义代码Fe 转义序列的文本。 通过此更改,将正确处理使用 ANSI 序列输出文本的程序。

© www.soinside.com 2019 - 2024. All rights reserved.