0

Instead of printing colored, the following script prints not colored.

s = '1\x1b[1;31m2\x1b[0m3'
print(s)
s = s.replace('1', ' ')
print(s)

I understand that it is because the .replace operation has broken the ANSI escape codes. But this is unfortunate.

What's an easy way to make .replace, or str.translate, or re.sub safely ignore escape codes?

iago-lito
  • 3,098
  • 3
  • 29
  • 54
  • Using unicode string manuplation it should be a doable thing. ```s = u'1\x1b[1;31m2\x1b[0m3'``` for main string. Then ```s = s.replace(u'1', u' ')``` to change chars using unicode comparison. Also ```b'1\x1b[1;31m2\x1b[0m3'``` binary string are widely used in CLI interfaces. – furkanayd Dec 03 '19 at 13:12
  • @furkanayd I'm not sure I understand what you mean. Are you *wishing* that such a manipulation be possible? Or are you claiming that `s = s.replace(u'1', u' ')` works the way I expect? – iago-lito Dec 03 '19 at 13:25
  • I am not 100% sure but we are using a lot of SSH, Telnet, and CLI outputs which are all in binary and we cast them as ascii to classify the unreadable text. It is worth to try assume. – furkanayd Dec 03 '19 at 13:28

1 Answers1

1

Using the regex to match ANSI escape sequences from an earlier answer, we can make a helper function that only replaces those parts of the text that do not belong to such a sequence.

Assuming this is utils.py:

import re

# https://stackoverflow.com/a/14693789/18771
ANSICODE = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')

def replace_ansi(imput_str, search_str, replace_str):
    pos = 0
    result = []
    for m in ANSICODE.finditer(imput_str):
        text = imput_str[pos:m.start()]
        text = text.replace(search_str, replace_str)
        result.append(text)
        result.append(m.group())
        pos = m.end()

    text = imput_str[pos:]
    result.append(text)
    return ''.join(result)

usage

from utils import replace_ansi

s1 = 'bla 1\x1b[1;31mbla 2\x1b[0mbla 3'
s2 = replace_ansi(s1, '1', 'X')
print(s1)
print(s2)

prints

bla 1[1;31mbla 2[0mbla 3
bla X[1;31mbla 2[0mbla 3
Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • I get the idea, great :) Cheers. I assume this is just too specific enough to be brought into the standard library X) – iago-lito Dec 03 '19 at 14:25