2012-11-22 22 views
5

Mam skrypt w języku Pythona, który próbuje interpretować ślad danych zapisanych i odczytanych odpowiednio z stdout i stdin. Problem polega na tym, że te dane są przesiąknięte ucieczkami ANSI, o które nie dbam. Te wartości są kodowane JSON, więc wyglądają jak "\ 033 [A" i "\ 033] 0;". Właściwie nie potrzebuję interpretować kodów, ale muszę wiedzieć, ile znaków znajduje się w każdym z nich (zauważysz, że pierwsza sekwencja składa się z 6 znaków, a druga z 7). Czy istnieje prosty sposób odfiltrowania tych kodów z ciągów, które mam?Filtrowanie sekwencji escape ANSI

+0

Opcja 'Program colcrt' już to robi. Nie jest to w Pythonie, ale jeśli jest to wymagane, może być przeniesione lub opakowane. – tripleee

Odpowiedz

0

To dalekie od doskonałości, ale regex może Ci somwhere:

import re 
text = r'begin \033[A middle \033]0; end' 
print re.sub(r'\\[0-9]+(\[|\])[0-9]*;?[A-Z]?', '', text) 

już usuwa swoje dwa przykłady poprawnie.

0

FWIW, to Python regex wydawało się działać dla mnie. I właściwie nie wiem, czy to prawdziwe, ale empirycznie wydaje się działać:

r'\\033[\[\]]([0-9]{1,2}([;@][0-9]{0,2})*)*[mKP]?' 
1
#!/usr/bin/env python 
import re 

ansi_pattern = '\033\[((?:\d|;)*)([a-zA-Z])' 
ansi_eng = re.compile(ansi_pattern) 

def strip_escape(string=''): 
    lastend = 0 
    matches = [] 
    newstring = str(string) 
    for match in ansi_eng.finditer(string): 
     start = match.start() 
     end = match.end() 
     matches.append(match) 
    matches.reverse() 
    for match in matches: 
     start = match.start() 
     end = match.end() 
     string = string[0:start] + string[end:] 
    return string 

if __name__ == '__main__': 
    import sys 
    import os 

    lname = sys.argv[-1] 
    fname = os.path.basename(__file__) 
    if lname != fname: 
     with open(lname, 'r') as fd: 
      for line in fd.readlines(): 
       print strip_escape(line).rstrip() 
    else: 
     USAGE = '%s <filename>' % fname 
     print USAGE 
6

Inny wariant:

def strip_ansi_codes(s): 
    """ 
    >>> import blessings 
    >>> term = blessings.Terminal() 
    >>> foo = 'hidden'+term.clear_bol+'foo'+term.color(5)+'bar'+term.color(255)+'baz' 
    >>> repr(strip_ansi_codes(foo)) 
    u'hiddenfoobarbaz' 
    """ 
    return re.sub(r'\x1b\[([0-9,A-Z]{1,2}(;[0-9]{1,2})?(;[0-9]{3})?)?[m|K]?', '', s) 
1

Ten pracował dla mnie:

re.sub(r'\x1b\[[\d;]+m', '', s)