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?

42
demandé sur Martijn Pieters 2013-02-04 23:07:04

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).

77
répondu Martijn Pieters 2017-12-20 16:17:34

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

36
répondu Jeff 2015-11-25 20:02:03

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()
17
répondu Édouard Lopez 2017-10-03 14:47:25

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 :)

7
répondu kfir 2017-08-01 21:47:25

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.

-1
répondu Neodied 2017-05-23 12:34:22