Non capisco DUE cose.
(1) È il tuo codice, sotto il tuo controllo. Vuoi aggiungere sequenze di escape ai tuoi dati e poi eliminarli nuovamente in modo da poter calcolare la lunghezza dei tuoi dati ?? Sembra molto più semplice calcolare il padding prima del aggiungendo le sequenze di escape. Cosa mi manca?
Supponiamo che nessuna delle sequenze di escape cambi la posizione del cursore. Se lo fanno, la risposta attualmente accettata non funzionerà comunque.
Supponiamo di avere i dati di stringa per ogni colonna (prima di aggiungere sequenze di escape) in un elenco denominato string_data
e le larghezze di colonna predeterminate si trovano in un elenco denominato width
. Provare qualcosa di simile:
temp = []
for colx, text in enumerate(string_data):
npad = width[colx] - len(text) # calculate padding size
assert npad >= 0
enhanced = fancy_text(text, colx, etc, whatever) # add escape sequences
temp.append(enhanced + " " * npad)
sys.stdout.write("".join(temp))
Aggiornamento dopo il commento del PO "" "Il motivo che voglio mettere a nudo fuori e calcolare la lunghezza dopo la stringa contiene i codici di colore è dovuto al fatto che tutti i dati è costruito a livello di codice. Ho un sacco di metodi di colorizzazione e sto costruendo i dati qualcosa del genere: str = "% s /% s /% s"% (VERDE (dati1), BLU (dati2), ROSSO (dati3)) Sarebbe essere abbastanza difficile da colorare il testo dopo il fatto. "" "
Se i dati sono costituiti da pezzi ciascuno con la propria formattazione, è ancora possibile calcolare la lunghezza e il pad visualizzati, a seconda dei casi. Ecco una funzione che fa che per i contenuti una cella:
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(40, 48)
BOLD = 1
def render_and_pad(reqd_width, components, sep="/"):
temp = []
actual_width = 0
for fmt_code, text in components:
actual_width += len(text)
strg = "\x1b[%dm%s\x1b[m" % (fmt_code, text)
temp.append(strg)
if temp:
actual_width += len(temp) - 1
npad = reqd_width - actual_width
assert npad >= 0
return sep.join(temp) + " " * npad
print repr(
render_and_pad(20, zip([BOLD, GREEN, YELLOW], ["foo", "bar", "zot"]))
)
se si pensa che la chiamata viene sovraccaricato dalla punteggiatura, si potrebbe fare qualcosa di simile:
BOLD = lambda s: (1, s)
BLACK = lambda s: (40, s)
# etc
def render_and_pad(reqd_width, sep, *components):
# etc
x = render_and_pad(20, '/', BOLD(data1), GREEN(data2), YELLOW(data3))
(2) Non capisco perché non si desidera utilizzare il kit di espressioni regolari fornito con Python. No "aggiustamenti" (per ogni possibile significato di "aggiustamenti" che io sappia) è coinvolto:
>>> import re
>>> test = "1\x1b[a2\x1b[42b3\x1b[98;99c4\x1b[77;66;55d5"
>>> expected = "12345"
>>> # regex = re.compile(r"\x1b\[[;\d]*[A-Za-z]")
... regex = re.compile(r"""
... \x1b # literal ESC
... \[ # literal [
... [;\d]* # zero or more digits or semicolons
... [A-Za-z] # a letter
... """, re.VERBOSE)
>>> print regex.findall(test)
['\x1b[a', '\x1b[42b', '\x1b[98;99c', '\x1b[77;66;55d']
>>> actual = regex.sub("", test)
>>> print repr(actual)
'12345'
>>> assert actual == expected
>>>
Aggiornamento dopo il commento del PO "" "Continuo a preferire la risposta di Paolo dal momento che è più conciso"" "
Più conciso che cosa? La soluzione regex non è abbastanza concisa per voi:
# === setup ===
import re
strip_ANSI_escape_sequences_sub = re.compile(r"""
\x1b # literal ESC
\[ # literal [
[;\d]* # zero or more digits or semicolons
[A-Za-z] # a letter
""", re.VERBOSE).sub
def strip_ANSI_escape_sequences(s):
return strip_ANSI_escape_sequences_sub("", s)
# === usage ===
raw_data = strip_ANSI_escape_sequences(formatted_data)
??
[Sopra codice corretto dopo @ Nick Perkins ha sottolineato che non ha funzionato]
Questi sono effettivamente "ANSI" codici colore, non "ASCII", come sarebbe mostrato su un terminale ANSI colore, o su un PC mediante il driver ANSI.SYS. – PaulMcG