如何从python中的字符串中删除ANSI转义序列

Spa*_*ero 58 python string escaping ansi-escape

这是我的字符串:

'ls\r\n\x1b[00m\x1b[01;31mexamplefile.zip\x1b[00m\r\n\x1b[01;31m'
Run Code Online (Sandbox Code Playgroud)

我正在使用代码从SSH命令检索输出,我希望我的字符串只包含'examplefile.zip'

我可以用什么来删除额外的转义序列?

Mar*_*ers 105

使用正则表达式删除它们:

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)
Run Code Online (Sandbox Code Playgroud)

演示:

ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
result = ansi_escape.sub('', sometext)
Run Code Online (Sandbox Code Playgroud)

(我已经整理了转义序列表达式,以遵循ANSI转义码的维基百科概述,重点关注CSI序列,忽略C1代码,因为它们从未在今天的UTF-8世界中使用过).


Jef*_*eff 43

此问题的接受答案仅考虑颜色和字体效果.有许多序列不以'm'结尾,例如光标定位,擦除和滚动区域.

控制序列(又名ANSI转义序列)的完整正则表达式是

/(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]/
Run Code Online (Sandbox Code Playgroud)

请参阅ECMA-48第5.4节ANSI转义码

  • OSC是一种"ANSI转义序列",经常被使用,并且将以不同的模式开始.你的答案是**不完整**. (3认同)
  • 我看到这个答案存在三个问题:1) `/.../` *不是 Python 语法*,而是您在 VI、Perl 或 awk 中使用的语法。2) `\x9B` 开启符(对于 CSI 代码)与 UTF-8 不兼容,因此现在很少使用,并且 ESC `[` 是首选,3) 您的模式仅涵盖 CSI 代码,而不是 ANSI 转义的整个范围(其中不仅包括 Thomas Dickly 提到的 OSC,还包括 SS2、SS3、DCS、ST、OSC、SOS、PM、APC 和 RIS)! (3认同)

Édo*_*pez 26

功能

基于的Martijn Pieters的♦的回答杰夫的正则表达式.

def escape_ansi(line):
    ansi_escape = re.compile(r'(?:\x1B[@-_]|[\x80-\x9F])[0-?]*[ -/]*[@-~]')
    return ansi_escape.sub('', line)
Run Code Online (Sandbox Code Playgroud)

测试

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')
Run Code Online (Sandbox Code Playgroud)

测试

如果你想自己运行它,使用python3(更好的unicode支持,blablabla).以下是测试文件的格式:

import unittest
import re

def escape_ansi(line):
    …

class TestStringMethods(unittest.TestCase):
    def test_remove_ansi_escape_sequence(self):
    …

if __name__ == '__main__':
    unittest.main()
Run Code Online (Sandbox Code Playgroud)

  • 我的正则表达式早已扩展到涵盖所有 ANSI C1 代码(7 位),今天我还添加了一个单独的 8 位变体。 (2认同)

小智 7

建议的正则表达式没有为我做的伎俩,所以我创建了自己的一个.以下是我根据此处的规范创建的python正则表达式

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)
Run Code Online (Sandbox Code Playgroud)

我在下面的代码片段上测试了我的正则表达式(基本上是来自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
Run Code Online (Sandbox Code Playgroud)

希望这会有助于其他人:)

  • 最后但并非最不重要的一点是,您的正则表达式实际上无法*删除问题示例中的完整 ANSI 代码*,因为它留下了“m”最后一个字节。 (2认同)