Color escape codes in pretty printed columns

那年仲夏 提交于 2019-11-30 08:29:52

问题


I have a tab-delimited text file which I send to column to "pretty print" a table.

Original file:

1<TAB>blablablabla<TAB>aaaa bbb ccc
2<TAB>blabla<TAB>xxxxxx
34<TAB>okokokok<TAB>zzz yyy

Using column -s$'\t' -t <original file>, I get

1  blablablabla aaaa bbb xxx
2  blabla       xxxxxx
34 okokokok     zzz yyy

as desired. Now I want to add colors to the columns. I tried to add the escape codes around each tab-delimited field in the original file. column successfully prints in color, but the columns are no longer aligned. Instead, it just prints the TAB separators verbatim.

The question is: how can I get the columns aligned, but also with unique colors?

I've thought of two ways to achieve this:

  1. Adjust the column parameters to make the alignment work with color codes
  2. Redirect the output of column to another file, and do a search+replace on the first two whitespace-delimited fields (the first two columns are guaranteed to not contain spaces; the third column most likely will contain spaces, but no TAB characters)

Problem is, I'm not sure how to do either of those two...

For reference, here is what I'm passing to column:

Note that the fields are indeed separated by TAB characters. I've confirmed this with od.

edit:

There doesn't seem to be an issue with the colorization. I already have the file shown above with the color codes working. The issue is column won't align once I send it input with escape codes. I am thinking of passing the fields without color codes to column, then copying the exact number of spaces column output between each field, and using that in a pretty print scheme.


回答1:


I wrote a bash version of column (similar to the one from util-linux) which works with color codes:

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

Example usage:

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

Output example:




回答2:


I would use awk for the colorization (sed can be used as well):

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 

and pipe it to column for the alignment:

... | column -s$'\t' -t

Output:




回答3:


A solution using printf to format the ouput as well :

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



来源:https://stackoverflow.com/questions/20151601/color-escape-codes-in-pretty-printed-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!