파이썬의 문자열에서 ANSI 이스케이프 시퀀스를 제거하는 방법
이것은 내 문자열입니다.
'ls\r\n\x1b[00m\x1b[01;31mexamplefile.zip\x1b[00m\r\n\x1b[01;31m'
SSH 명령에서 출력을 검색하는 코드를 사용하고 있었고 내 문자열에 'examplefile.zip'만 포함하고 싶습니다.
추가 이스케이프 시퀀스를 제거하기 위해 무엇을 사용할 수 있습니까?
정규 표현식으로 삭제하십시오.
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)
또는 VERBOSE
플래그 없이 압축 된 형식으로 :
ansi_escape = re.compile(r'\x1B[@-_][0-?]*[ -/]*[@-~]')
result = ansi_escape.sub('', sometext)
데모:
>>> 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'
위의 정규식은 모든 7 비트 ANSI C1 이스케이프 시퀀스를 다루지 만 8 비트 C1 이스케이프 시퀀스 오프너는 다루지 않습니다 . 후자는 동일한 범위의 바이트가 다른 의미를 갖는 오늘날의 UTF-8 세계에서 사용되지 않습니다.
8 비트 코드도 다룰 필요가 있고 bytes
값으로 작업하는 경우 정규식은 다음과 같은 바이트 패턴이됩니다.
# 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)
압축 될 수있는
# 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)
자세한 내용은 다음을 참조하십시오.
- Wikipedia 의 ANSI 이스케이프 코드 개요
- ECMA-48 표준, 5 판 (특히 섹션 5.3 및 5.3)
제공 한 예제에는 \x1B[
또는 ESC[
여는 바이트 로 표시되는 4 개의 CSI (Control Sequence Introducer) 코드 가 포함되어 있으며 각 코드에는 SGR (Select Graphic Rendition) 코드가 포함되어 있습니다 m
. 이들 ;
사이 의 매개 변수 ( 세미콜론 으로 구분)는 사용할 그래픽 변환 속성을 터미널에 알려줍니다. 따라서 각 \x1B[....m
시퀀스 에 대해 사용되는 3 개의 코드는 다음과 같습니다.
- 0 (또는
00
이 예에서) : reset , 모든 속성 비활성화 - 1 (또는
01
예에서) : 굵게 - 31 : 빨간색 (전경)
그러나 ANSI에는 CSI SGR 코드보다 더 많은 것이 있습니다. CSI만으로도 커서를 제어하고, 라인을 지우거나 전체 디스플레이를 제어하거나 스크롤 할 수 있습니다 (물론 터미널이이를 지원하는 경우). 그리고 CSI 외에도 대체 글꼴 ( SS2
및 SS3
) 을 선택 하고 , '비공개 메시지'(비밀번호 생각)를 전송하고, 터미널 ( DCS
), OS ( OSC
) 또는 애플리케이션 자체 () APC
와 통신하는 코드가 있습니다. 사용자 정의 제어 코드를 통신 스트림에 피기 백)하고 문자열을 정의하는 데 도움이되는 추가 코드 ( SOS
, 문자열의 시작, ST
문자열 종결 자) 또는 모든 것을 기본 상태로 다시 재설정 ( RIS
)합니다. 위의 정규식은이 모든 것을 다룹니다.
이 질문에 대한 대답은 색상과 글꼴 효과 만 고려합니다. 커서 위치 지정, 지우기 및 스크롤 영역과 같이 'm'으로 끝나지 않는 시퀀스가 많이 있습니다.
제어 시퀀스 (ANSI 이스케이프 시퀀스라고도 함)에 대한 완전한 정규식은 다음과 같습니다.
/(\x9B|\x1B\[)[0-?]*[ -\/]*[@-~]/
를 참조하십시오 ECMA-48 5.4 절 및 ANSI 이스케이프 코드
함수
Jeff의 regexp 에 대한 Martijn 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')
테스팅
혼자서 실행하려면 python3
(더 나은 유니 코드 지원, 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()
제안 된 정규식은 나를 위해 트릭을 수행하지 않았으므로 내 자신의 것을 만들었습니다. 다음은 여기 에서 찾은 사양을 기반으로 만든 파이썬 정규식입니다.
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
바라건대 이것은 다른 사람들에게 도움이 될 것입니다 :)
미래의 Stack Overflowers에 도움이된다면 크레용 라이브러리 를 사용 하여 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))
if you want to remove the \r\n
bit, you can pass the string through this function (written by 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
Careful though, this will lump together the text in front and behind the escape sequences. So, using Martijn's filtered string 'ls\r\nexamplefile.zip\r\n'
, you will get lsexamplefile.zip
. Note the ls
in front of the desired filename.
I would use the stripEscape function first to remove the escape sequences, then pass the output to Martijn's regular expression, which would avoid concatenating the unwanted bit.
ReferenceURL : https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python
'UFO ET IT' 카테고리의 다른 글
포인터의 크기는 얼마입니까? (0) | 2021.01.09 |
---|---|
자바에서 호출자 클래스를 얻는 방법 (0) | 2021.01.09 |
`is` 키워드는 타이프 스크립트에서 무엇을합니까? (0) | 2021.01.08 |
네트워크 중단 후 자동으로 (또는 더 쉽게) 화면 세션에 다시 연결 (0) | 2021.01.08 |
C #에 Dictionary <>와 같은 클래스가 있지만 키에만 값이 없습니까? (0) | 2021.01.08 |