Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting correct string length in Python for strings with ANSI color codes

Tags:

I've got some Python code that will automatically print a set of data in a nice column format, including putting in the appropriate ASCII escape sequences to color various pieces of the data for readability.

I eventually end up with each line being represented as a list, with each item being a column that is space-padded so that the same columns on each line are always the same length. Unfortunately when I actually go to print this, not all the columns line up. I suspect this is to do with the ASCII escape sequences - because the len function doesn't seem to recognize these:

>>> a = '\x1b[1m0.0\x1b[0m' >>> len(a) 11 >>> print a 0.0 

And so while each column is the same length according to len, they are not actually the same length when printed on the screen.

Is there any way (save for doing some hackery with regular expressions which I'd rather not do) to take the escaped string and find out what the printed length is so I can space pad appropriately? Maybe some way to just "print" it back to string and examine the length of that?

like image 450
Paul D. Avatar asked Feb 02 '10 19:02

Paul D.


People also ask

How will you get the length of the string in Python?

Using the len() method To calculate the length of a string in Python, you can use the built-in len() method. It takes a string as a parameter and returns an integer as the length of that string. For example len(“educative”) will return 9 because there are 9 characters in “educative”.


1 Answers

The pyparsing wiki includes this helpful expression for matching on ANSI escape sequences:

ESC = Literal('\x1b') integer = Word(nums) escapeSeq = Combine(ESC + '[' + Optional(delimitedList(integer,';')) +                  oneOf(list(alphas))) 

Here's how to make this into an escape-sequence-stripper:

from pyparsing import *  ESC = Literal('\x1b') integer = Word(nums) escapeSeq = Combine(ESC + '[' + Optional(delimitedList(integer,';')) +                  oneOf(list(alphas)))  nonAnsiString = lambda s : Suppress(escapeSeq).transformString(s)  unColorString = nonAnsiString('\x1b[1m0.0\x1b[0m') print unColorString, len(unColorString) 

prints:

0.0 3 
like image 166
PaulMcG Avatar answered Sep 20 '22 13:09

PaulMcG