programing

파이썬의 문자열에서 ANSI 이스케이프 시퀀스를 제거하려면 어떻게 해야 합니까?

css3 2023. 8. 28. 21:17

파이썬의 문자열에서 ANSI 이스케이프 시퀀스를 제거하려면 어떻게 해야 합니까?

여기 제 문자열이 포함된 스니펫이 있습니다.
'ls\r\n\x1b[00m\x1b[01;31mexamplefile.zip\x1b[00m\r\n\x1b[01;31m'

내가 실행한 SSH 명령에서 문자열이 반환되었습니다.문자열에 ANSI 표준 이스케이프 시퀀스가 포함되어 있기 때문에 현재 상태에서 사용할 수 없습니다.이스케이프 시퀀스를 프로그래밍 방식으로 제거하여 남은 문자열의 유일한 부분은 다음과 같습니다.

정규식으로 삭제:

import re

# 7-bit C1 ANSI sequences
ansi_escape = re.compile(r'''
    \x1B  # ESC
    (?:   # 7-bit C1 Fe (except CSI)
        [@-Z\\-_]
    |     # or [ for CSI, followed by a control sequence
        \[
        [0-?]*  # Parameter bytes
        [ -/]*  # Intermediate bytes
        [@-~]   # Final byte
    )
''', re.VERBOSE)
result = ansi_escape.sub('', sometext)

면니없 없이, 것이그아.VERBOSE플래그, 축약된 형식:

ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
result = ansi_escape.sub('', sometext)

데모:

>>> import re
>>> ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[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'

위의 정규식은 모든 7비트 ANSI C1 이스케이프 시퀀스를 포함하지만 8비트 C1 이스케이프 시퀀스 오퍼레이터는 포함하지 않습니다.후자는 같은 범위의 바이트가 다른 의미를 갖는 오늘날의 UTF-8 세계에서는 사용되지 않습니다.

만약 당신이 8비트 코드도 다룰 필요가 있다면 (아마도)bytesvalues)다음과 .

# 7-bit and 8-bit C1 ANSI sequences
ansi_escape_8bit = re.compile(br'''
    (?: # either 7-bit C1, two bytes, ESC Fe (omitting CSI)
        \x1B
        [@-Z\\-_]
    |   # or a single 8-bit byte Fe (omitting CSI)
        [\x80-\x9A\x9C-\x9F]
    |   # or CSI + control codes
        (?: # 7-bit CSI, ESC [ 
            \x1B\[
        |   # 8-bit CSI, 9B
            \x9B
        )
        [0-?]*  # Parameter bytes
        [ -/]*  # Intermediate bytes
        [@-~]   # Final byte
    )
''', re.VERBOSE)
result = ansi_escape_8bit.sub(b'', somebytesvalue)

에 요약할 수 있는.

# 7-bit and 8-bit C1 ANSI sequences
ansi_escape_8bit = re.compile(
    br'(?:\x1B[@-Z\\-_]|[\x80-\x9A\x9C-\x9F]|(?:\x1B\[|\x9B)[0-?]*[ -/]*[@-~])'
)
result = ansi_escape_8bit.sub(b'', somebytesvalue)

자세한 내용은 다음을 참조하십시오.

의 CSI Introducer), "Control Sequence Introducer" 4개의 CSI(Control Sequence Introducer) 코드가 표시되어 .\x1B[또는 ESC를 여는 바이트, 그리고 각각은 SGR (Select Graphic Rendition) 코드를 포함합니다. 왜냐하면 그것들은 각각 다음과 같이 끝나기 때문입니다.m 」(「 」)로 );세미콜론(semicolon)은 사용할 그래픽 렌더링 속성을 단말기에 알려줍니다. 각각의 래서각자에 요.\x1B[....m시퀀스에 사용되는 3가지 코드는 다음과 같습니다.

  • 0(또는)00이 예에서는): 재설정, 모든 특성 사용 안 함
  • 1(또는)01예제): 굵게 표시
  • 31: 빨간색(전경)

그러나 ANSI에는 CSI SGR 코드 이상의 것이 있습니다.CSI 단독으로 커서, 선 또는 전체 디스플레이를 지우거나 스크롤할 수도 있습니다(물론 단말기가 이를 지원하는 경우).CSI 에도 대체폰트를 코드가 (Code to select fonts).SS2그리고.SS3 ' 메시지passwords하기 위해(), '메시지를 보냅니다.DCS(), OS(OSC 응용 자체입니다.APC이 사용자 ) 하는 데 (예: 문자열 정의)SOS of String, 문열시작자,,ST Terminator) 모든 기본 상태(String Terminator)로합니다.RIS은 이 것을 위의 정규식은 이 모든 것을 포함합니다.

그러나 위 정규식은 ANSI C1 코드만 제거하고 해당 코드가 표시할 수 있는 추가 데이터(예: OSC 오프너와 종료 ST 코드 사이에 전송되는 문자열)는 제거하지 않습니다.이러한 항목을 제거하려면 이 답변의 범위를 벗어나는 추가 작업이 필요합니다.

허용된 답변은 전경 색상 및 텍스트 스타일을 변경하도록 포맷된 ANSI 표준화된 이스케이프 시퀀스만 고려합니다.많은 시퀀스가 다음으로 끝나지 않습니다.'m'예: 커서 위치 지정, 지우기 및 스크롤 영역.아래의 패턴은 전경색과 텍스트 스타일을 설정하는 것을 넘어 모든 경우를 포함하려고 시도합니다.


다음은 ANSI 표준 제어 시퀀스에 대한 정규식입니다.
/(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]/


추가 참조:

기능.

Jeff의 정규 표현에 대한 Martjn Pieters♦의 답변을 기반으로 합니다.

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

테스트

직접실려사다용다니합음을면하행다사니▁if▁use합▁it▁by를 사용합니다.python3(유니코드 지원 향상, blabla).테스트 파일은 다음과 같습니다.

import unittest
import re

def escape_ansi(line):
    …

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

if __name__ == '__main__':
    unittest.main()

제안된 정규식이 저에게 도움이 되지 않아서 저는 저만의 정규식을 만들었습니다.다음은 여기에 있는 사양을 기반으로 만든 파이썬 정규식입니다.

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)

다음 스니펫에서 정규식을 테스트했습니다(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

이것이 다른 사람들에게 도움이 되기를 바랍니다 :)

OSC 시퀀스를 사용하는 경우 정규식 솔루션이 작동하지 않았습니다(\x1b])

실제로 가시적인 출력을 렌더링하려면 파이테와 같은 터미널 에뮬레이터가 필요합니다.

#! /usr/bin/env python3

import pyte # terminal emulator: render terminal output to visible characters

pyte_screen = pyte.Screen(80, 24)
pyte_stream = pyte.ByteStream(pyte_screen)

bytes_ = b''.join([
  b'$ cowsay hello\r\n', b'\x1b[?2004l', b'\r', b' _______\r\n',
  b'< hello >\r\n', b' -------\r\n', b'        \\   ^__^\r\n',
  b'         \\  (oo)\\_______\r\n', b'            (__)\\       )\\/\\\r\n',
  b'                ||----w |\r\n', b'                ||     ||\r\n',
  b'\x1b]0;user@laptop1:/tmp\x1b\\', b'\x1b]7;file://laptop1/tmp\x1b\\', b'\x1b[?2004h$ ',
])
pyte_stream.feed(bytes_)

# pyte_screen.display always has 80x24 characters, padded with whitespace
# -> use rstrip to remove trailing whitespace from all lines
text = ("".join([line.rstrip() + "\n" for line in pyte_screen.display])).strip() + "\n"
print("text", text)

print("cursor", pyte_screen.cursor.y, pyte_screen.cursor.x)
print("title", pyte_screen.title)

향후 스택 오버플로에 도움이 된다면 크레용 라이브러리를 사용하여 Python 출력에 시각적인 영향을 조금 더 주고 있었는데, 이는 Windows와 Linux 플랫폼 모두에서 작동하기 때문에 유리합니다.하지만 저는 화면에 표시할 뿐만 아니라 로그 파일에 추가할 수도 있었고, 탈출 시퀀스가 로그 파일의 가독성에 영향을 미치고 있었기 때문에 로그 파일을 제거하고 싶었습니다.그러나 크레용으로 삽입된 탈출 시퀀스에서 오류가 발생했습니다.

expected string or bytes-like object

해결책은 매개 변수를 문자열에 캐스팅하여 일반적으로 허용되는 답변에 대한 약간의 수정만 필요했습니다.

def escape_ansi(line):
    ansi_escape = re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]')
    return ansi_escape.sub('', str(line))

제거하려면\r\n비트, 다음 함수를 통해 문자열을 전달할 수 있습니다(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

그러나 이렇게 하면 이스케이프 시퀀스 앞과 뒤의 텍스트가 함께 표시됩니다.그래서 마르틴의 필터링된 문자열을 사용하여'ls\r\nexamplefile.zip\r\n'얻게 될 것입니다lsexamplefile.zip에 하십시오.ls원하는 파일 이름 앞에 있습니다.

먼저 stripEscape 함수를 사용하여 이스케이프 시퀀스를 제거한 다음 출력을 Martjn의 정규식으로 전달하여 불필요한 비트가 연결되지 않도록 할 것입니다.

파이썬 3.5를 사용하는 2020년의 경우만큼 쉽습니다.string.encode().decode('ascii')

ascii_string = 'ls\r\n\x1b[00m\x1b[01;31mexamplefile.zip\x1b[00m\r\n\x1b[01;31m'
decoded_string = ascii_string.encode().decode('ascii')
print(decoded_string) 

>ls
>examplefile.zip
>

언급URL : https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python