Voici ma chaîne:
'ls\r\n\x1b[00m\x1b[01;31mexamplefile.Zip\x1b[00m\r\n\x1b[01;31m'
J'utilisais du code pour récupérer la sortie d'une commande SSH et je veux que ma chaîne contienne uniquement 'examplefile.Zip'
Que puis-je utiliser pour supprimer les séquences d'échappement supplémentaires?
Supprimez-les avec une expression régulière:
import re
# 7-bit C1 ANSI sequences
ansi_escape = re.compile(r'''
\x1B # ESC
[@-_] # 7-bit C1 Fe
[0-?]* # Parameter bytes
[ -/]* # Intermediate bytes
[@-~] # Final byte
''', re.VERBOSE)
result = ansi_escape.sub('', sometext)
ou, sans l'indicateur VERBOSE
, sous forme condensée:
ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
result = 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'
L'expression régulière ci-dessus couvre toutes les séquences d'échappement ANSI C1 7 bits, mais pas les ouvreurs de séquence d'échappement C1 8 bits. Ces derniers ne sont jamais utilisés dans le monde UTF-8 actuel où la même plage d'octets a une signification différente.
Si vous avez également besoin de couvrir les codes 8 bits (et que vous travaillez alors vraisemblablement avec des valeurs bytes
), l'expression régulière devient un modèle d'octets comme celui-ci:
# 7-bit and 8-bit C1 ANSI sequences
ansi_escape_8bit = re.compile(br'''
(?: # either 7-bit C1, two bytes, ESC Fe
\x1B
[@-_]
| # or a single 8-bit byte Fe
[\x80-\x9F]
)
[0-?]* # Parameter bytes
[ -/]* # Intermediate bytes
[@-~] # Final byte
''', re.VERBOSE)
result = ansi_escape_8bit.sub(b'', somebytesvalue)
qui peut être condensé jusqu'à
# 7-bit and 8-bit C1 ANSI sequences
ansi_escape_8bit = re.compile(br'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
result = ansi_escape_8bit.sub(b'', somebytesvalue)
Pour plus d'informations, voir:
L'exemple que vous avez donné contient 4 codes CSI (Control Sequence Introducer), marqués par le \x1B[
ou ESC [
octets d'ouverture, et chacun contient un code SGR (Select Graphic Rendition), car ils se terminent chacun par m
. Les paramètres (séparés par ;
points-virgules) entre ceux-ci indiquent à votre terminal les attributs de rendu graphique à utiliser. Donc pour chaque \x1B[....m
séquence, les 3 codes utilisés sont:
00
dans cet exemple): reset , désactivez tous les attributs01
dans l'exemple): bold Cependant, ANSI ne se limite pas aux codes CSI SGR. Avec CSI seul, vous pouvez également contrôler le curseur, effacer les lignes ou tout l'affichage, ou faire défiler (à condition que le terminal le prenne bien sûr en charge). Et au-delà de CSI, il existe des codes pour sélectionner des polices alternatives (SS2
et SS3
), pour envoyer des "messages privés" (pensez aux mots de passe), pour communiquer avec le terminal (DCS
), le système d'exploitation (OSC
) ou l'application elle-même (APC
, un moyen pour les applications de superposer des codes de contrôle personnalisés sur le flux de communication) et d'autres codes pour aider à définir des chaînes (SOS
, début de chaîne, ST
terminaison de chaîne) ou à réinitialiser tout à un état de base (RIS
). Les expressions rationnelles ci-dessus couvrent tous ces éléments.
La réponse acceptée à cette question ne prend en compte que les effets de couleur et de police. Il y a beaucoup de séquences qui ne se terminent pas par "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 séquences d'échappement ANSI) est
/(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]/
Reportez-vous à ECMA-48 section 5.4 et code d'échappement ANSI
Basé sur réponse de Martijn Pieters ♦ avec regexp de Jeff .
def escape_ansi(line):
ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
return ansi_escape.sub('', line)
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')
Si vous souhaitez l'exécuter par vous-même, utilisez python3
(meilleur support unicode, blablabla). Voici comment le fichier de test doit être:
import unittest
import re
def escape_ansi(line):
…
class TestStringMethods(unittest.TestCase):
def test_remove_ansi_escape_sequence(self):
…
if __== '__main__':
unittest.main()
Le regex suggéré n'a pas fait l'affaire pour moi, alors j'ai créé le mien. Ce qui suit est un python regex que j'ai créé sur la base des spécifications trouvées 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 expression régulière sur l'extrait de code suivant (essentiellement un copier-coller de la page ascii-table.com)
\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 les autres :)