Comment puis-je supprimer les séquences d'échappement ANSI d'une chaîne en python
C'est ma chaîne:
'lsrnx1b[00mx1b[01;31mexamplefile.zipx1b[00mrnx1b[01;31m'
j'utilisais le code pour récupérer la sortie d'une commande SSH et je veux que ma chaîne ne contienne que 'exemplefile.zip '
Que puis-je utiliser pour supprimer les séquences d'échappement supplémentaires?
5 réponses
les supprimer avec une expression régulière:
import re
ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
ansi_escape.sub('', sometext)
Démo:
>>> import re
>>> ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
>>> sometext = 'ls\r\n\x1b[00m\x1b[01;31mexamplefile.zip\x1b[00m\r\n\x1b[01;31m'
>>> ansi_escape.sub('', sometext)
'ls\r\nexamplefile.zip\r\n'
(j'ai modifié l'expression de la séquence d'échappement pour suivre l'aperçu Wikipédia des codes d'échappement ANSI , en se concentrant sur les séquences CSI, et en ignorant les codes C1 car ils ne sont jamais utilisés dans le monde UTF-8 d'aujourd'hui).
la réponse acceptée à cette question ne tient compte que des effets de couleur et de police. Il y a beaucoup de séquences qui ne se terminent pas en 'm', comme le positionnement du curseur, l'effacement et les régions de défilement.
le regexp complet pour les séquences de contrôle (Alias ANSI Escape Sequences) est
/(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]/
Consultez ECMA-48 Section 5.4 et code d'échappement ANSI
fonction
Basé sur Martijn Pieters♦'s réponse avec de Jeff regexp .
def escape_ansi(line):
ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', line)
Test
def test_remove_ansi_escape_sequence(self):
line = '\t\u001b[0;35mBlabla\u001b[0m \u001b[0;36m172.18.0.2\u001b[0m'
escaped_line = escape_ansi(line)
self.assertEqual(escaped_line, '\tBlabla 172.18.0.2')
test
si vous voulez l'exécuter vous-même, utilisez python3
(meilleur support unicode, blablabla). Voici comment le fichier test devrait être:
import unittest
import re
def escape_ansi(line):
…
class TestStringMethods(unittest.TestCase):
def test_remove_ansi_escape_sequence(self):
…
if __name__ == '__main__':
unittest.main()
le regex suggéré n'a pas fait le tour pour moi donc j'ai créé un de mes propres. Ce qui suit est un regex python que j'ai créé sur la base de la spécification trouvée ici
ansi_regex = r'\x1b(' \
r'(\[\??\d+[hl])|' \
r'([=<>a-kzNM78])|' \
r'([\(\)][a-b0-2])|' \
r'(\[\d{0,2}[ma-dgkjqi])|' \
r'(\[\d+;\d+[hfy]?)|' \
r'(\[;?[hf])|' \
r'(#[3-68])|' \
r'([01356]n)|' \
r'(O[mlnp-z]?)|' \
r'(/Z)|' \
r'(\d+)|' \
r'(\[\?\d;\d0c)|' \
r'(\d;\dR))'
ansi_escape = re.compile(ansi_regex, flags=re.IGNORECASE)
j'ai testé mon regex sur le snippet suivant (essentiellement une pâte de copie de la ascii-table.com page)
\x1b[20h Set
\x1b[?1h Set
\x1b[?3h Set
\x1b[?4h Set
\x1b[?5h Set
\x1b[?6h Set
\x1b[?7h Set
\x1b[?8h Set
\x1b[?9h Set
\x1b[20l Set
\x1b[?1l Set
\x1b[?2l Set
\x1b[?3l Set
\x1b[?4l Set
\x1b[?5l Set
\x1b[?6l Set
\x1b[?7l Reset
\x1b[?8l Reset
\x1b[?9l Reset
\x1b= Set
\x1b> Set
\x1b(A Set
\x1b)A Set
\x1b(B Set
\x1b)B Set
\x1b(0 Set
\x1b)0 Set
\x1b(1 Set
\x1b)1 Set
\x1b(2 Set
\x1b)2 Set
\x1bN Set
\x1bO Set
\x1b[m Turn
\x1b[0m Turn
\x1b[1m Turn
\x1b[2m Turn
\x1b[4m Turn
\x1b[5m Turn
\x1b[7m Turn
\x1b[8m Turn
\x1b[1;2 Set
\x1b[1A Move
\x1b[2B Move
\x1b[3C Move
\x1b[4D Move
\x1b[H Move
\x1b[;H Move
\x1b[4;3H Move
\x1b[f Move
\x1b[;f Move
\x1b[1;2 Move
\x1bD Move/scroll
\x1bM Move/scroll
\x1bE Move
\x1b7 Save
\x1b8 Restore
\x1bH Set
\x1b[g Clear
\x1b[0g Clear
\x1b[3g Clear
\x1b#3 Double-height
\x1b#4 Double-height
\x1b#5 Single
\x1b#6 Double
\x1b[K Clear
\x1b[0K Clear
\x1b[1K Clear
\x1b[2K Clear
\x1b[J Clear
\x1b[0J Clear
\x1b[1J Clear
\x1b[2J Clear
\x1b5n Device
\x1b0n Response:
\x1b3n Response:
\x1b6n Get
\x1b[c Identify
\x1b[0c Identify
\x1b[?1;20c Response:
\x1bc Reset
\x1b#8 Screen
\x1b[2;1y Confidence
\x1b[2;2y Confidence
\x1b[2;9y Repeat
\x1b[2;10y Repeat
\x1b[0q Turn
\x1b[1q Turn
\x1b[2q Turn
\x1b[3q Turn
\x1b[4q Turn
\x1b< Enter/exit
\x1b= Enter
\x1b> Exit
\x1bF Use
\x1bG Use
\x1bA Move
\x1bB Move
\x1bC Move
\x1bD Move
\x1bH Move
\x1b12 Move
\x1bI
\x1bK
\x1bJ
\x1bZ
\x1b/Z
\x1bOP
\x1bOQ
\x1bOR
\x1bOS
\x1bA
\x1bB
\x1bC
\x1bD
\x1bOp
\x1bOq
\x1bOr
\x1bOs
\x1bOt
\x1bOu
\x1bOv
\x1bOw
\x1bOx
\x1bOy
\x1bOm
\x1bOl
\x1bOn
\x1bOM
\x1b[i
\x1b[1i
\x1b[4i
\x1b[5i
j'espère que cela aidera d'autres personnes :)
si vous voulez supprimer le bit \r\n
, vous pouvez passer la chaîne à travers cette fonction ( écrit par sarnold ):
def stripEscape(string):
""" Removes all escape sequences from the input string """
delete = ""
i=1
while (i<0x20):
delete += chr(i)
i += 1
t = string.translate(None, delete)
return t
attention cependant, cela regroupera le texte devant et derrière les séquences d'évasion. Ainsi, en utilisant la chaîne filtrée de Martijn 'ls\r\nexamplefile.zip\r\n'
, vous obtiendrez lsexamplefile.zip
. Notez le ls
devant le nom de fichier souhaité.
j'utiliserais d'abord la fonction stripEscape pour supprimer les séquences d'échappement, puis passer la sortie à L'expression régulière de Martijn, ce qui éviterait de concaténer le bit indésirable.