IT

Python에서 노드의 이스케이프 시퀀스 처리

lottoking 2020. 9. 4. 07:46
반응형

Python에서 노드의 이스케이프 시퀀스 처리


파일이나 사용자로부터 입력을 공용면 이스케이프 시퀀스가 ​​포함 된 암호화를 얻습니다. 이스케이프 시퀀스 리터럴에서 이스케이프 시퀀스를 처리하는 것과 같은 방식으로 이스케이프 시퀀스를 처리하고 싶습니다 .

예를 들어 myString다음과 같이 정의 가정 해 보겠습니다 .

>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs

나는 수행하는 함수를 원한다 process.

>>> print(process(myString))
spam
eggs

함수가 Python의 모든 이스케이프 시퀀스를 처리 할 수 ​​있어야합니다 (위 링크의 표에 다음 됨).

어디에서 수행하는 기능이 있습니까?


올바른 방법은 '문자열 이스케이프'코드를 사용하여 사용하여 사용하는 것입니다.

>>> myString = "spam\\neggs"
>>> decoded_string = bytes(myString, "utf-8").decode("unicode_escape") # python3 
>>> decoded_string = myString.decode('string_escape') # python2
>>> print(decoded_string)
spam
eggs

AST 또는 eval을 사용하지 않습니다. 보다 많은 코덱을 사용하는 것이 안전합니다.


unicode_escape 일반적으로 작동하지 않습니다.

밝혀 그것은 string_escape또는 unicode_escape특히, 실제 유니 코드의 존재에 일을 하지 않습니다 - 솔루션은 일반적으로 작동하지 않습니다.

ASCII가 아닌 모든 문자가 이스케이프 된다고 확신 할 수있는 권한 (그리고 처음 128 개 초과하는 모든 문자는 ASCII가 아닙니다) unicode_escape입니다. 그러나 이미 ASCII가 아닌 문자가 있으면 문제가 발생합니다.

unicode_escape기본적으로 바이트를 유니 코드 텍스트로 변환하도록 설계했습니다. 그러나 많은 곳에서 (예 : Python 소스 코드) 소스 데이터는 이미 유니 코드 텍스트입니다.

첫번째 방법은 텍스트를 바이트로 인코딩하는 것입니다. UTF-8은 모든 텍스트에 실행하라는 메시지가 표시됩니다.

다음 예제는 Python 3에 있기 때문에 그렇다고 리터럴이 더 깨끗하지만 Python 2와 3 모두에서 약간 다른 표현으로 존재합니다.

>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve   test

글쎄, 그건 틀렸어.

텍스트를 텍스트로 사용하는 코덱을 사용하는 새로운 권장 방법은 codecs.decode직접 호출 하는 것입니다. 도움이 되나요?

>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve   test

아뇨. (또한 위는 Python 2의 UnicodeError입니다.)

unicode_escape코덱은, 그 이름에도 불구하고 모든 비 ASCII 바이트 라틴 -1 (ISO-8859-1) 인코딩에 가정하는 것이 검증되었습니다. 따라서 다음과 같이해야합니다.

>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve    test

그러나 그것은 끔찍합니다. 이것은 마치 유니 코드가 전혀 발명되지 않은 것처럼 256 개의 Latin-1 문자로 제한됩니다!

>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)

문제를 해결하기 위해 정규식 추가

(놀랍게도 두 가지 문제가 없습니다.)

우리가해야 할 일은 unicode_escape우리가 ASCII 텍스트라고 확신하는 것들 에만 디코더를 적용하는 것입니다. 특히 ASCII 텍스트로 보장되는 유효한 Python 이스케이프 시퀀스에만 적용 할 수 있습니다.

계획은 정규 표현식을 사용하여 이스케이프 시퀀스를 찾고, re.sub이스케이프되지 않은 값으로 대체 하기 위해 함수를 인수로 사용하는 것입니다.

import re
import codecs

ESCAPE_SEQUENCE_RE = re.compile(r'''
    ( \\U........      # 8-digit hex escapes
    | \\u....          # 4-digit hex escapes
    | \\x..            # 2-digit hex escapes
    | \\[0-7]{1,3}     # Octal escapes
    | \\N\{[^}]+\}     # Unicode characters by name
    | \\[\\'"abfnrtv]  # Single-character escapes
    )''', re.UNICODE | re.VERBOSE)

def decode_escapes(s):
    def decode_match(match):
        return codecs.decode(match.group(0), 'unicode-escape')

    return ESCAPE_SEQUENCE_RE.sub(decode_match, s)

그리고 그것으로 :

>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő     Rubik

파이썬 3에 대한 실제로 정확하고 편리한 대답 :

>>> import codecs
>>> myString = "spam\\neggs"
>>> print(codecs.escape_decode(bytes(myString, "utf-8"))[0].decode("utf-8"))
spam
eggs
>>> myString = "naïve \\t test"
>>> print(codecs.escape_decode(bytes(myString, "utf-8"))[0].decode("utf-8"))
naïve    test

에 관한 세부 사항 codecs.escape_decode:

  • codecs.escape_decode 바이트 단위 디코더입니다.
  • codecs.escape_decodeb"\\n"-> b"\n", b"\\xce"-> 와 같은 ASCII 이스케이프 시퀀스를 디코딩 b"\xce"합니다.
  • codecs.escape_decode 는 바이트 객체의 인코딩에 대해 신경 쓰지 않거나 알 필요가 없지만 이스케이프 된 바이트의 인코딩은 나머지 객체의 인코딩과 일치해야합니다.

배경:

  • @rspeer 가 정확합니다 : unicode_escapepython3에 대한 잘못된 솔루션입니다. 이는 unicode_escape이스케이프 된 바이트를 디코딩 한 다음 바이트를 유니 코드 문자열로 디코딩하지만 두 번째 작업에 사용할 코덱에 대한 정보를 수신하지 않기 때문입니다.
  • @Jerub 이 정확합니다 : AST 또는 eval을 피하십시오.
  • 나는 "Python3에서 어떻게 .decode ( 'string-escape')를합니까?"에 대한이 답변codecs.escape_decode 에서 처음 발견 했습니다. . 그 대답에서 알 수 있듯이 해당 함수는 현재 파이썬 3에 대해 문서화되지 않았습니다.

ast.literal_eval기능은 가깝게 있지만, 문자열이 제대로 첫번째 인용 될 것으로 예상됩니다.

물론 백 슬래시 이스케이프에 대한 Python의 해석은 문자열이 인용되는 방식 ( ""vs r""vs u"", 삼중 따옴표 등)에 따라 다르므로 사용자 입력을 적절한 따옴표로 묶고 literal_eval. 따옴표로 묶으 literal_eval면 숫자, 튜플, 사전 등이 반환 되지 않습니다 .

사용자가 문자열을 감싸려는 유형의 인용되지 않은 따옴표를 입력하면 여전히 까다로울 수 있습니다.


이것은 나쁜 방법이지만 문자열 인수로 전달 된 이스케이프 된 8 진수를 해석하려고 할 때 효과적이었습니다.

input_string = eval('b"' + sys.argv[1] + '"')

eval과 ast.literal_eval 사이에 차이가 있다는 점을 언급 할 가치가 있습니다 (eval이 훨씬 안전하지 않음). 파이썬의 eval () 대 ast.literal_eval () 사용하기를 참조하십시오 .


아래 코드는 작동해야합니다. \ n은 문자열에 표시되어야합니다.

import string

our_str = 'The String is \\n, \\n and \\n!'
new_str = string.replace(our_str, '/\\n', '/\n', 1)
print(new_str)

참고 URL : https://stackoverflow.com/questions/4020539/process-escape-sequences-in-a-string-in-python

반응형