Làm cách nào để bỏ thoát một chuỗi có dấu gạch chéo ngược?


100

Giả sử tôi có một chuỗi là phiên bản thoát dấu gạch chéo ngược của một chuỗi khác. Có cách nào dễ dàng, bằng Python, để bỏ qua chuỗi không? Ví dụ, tôi có thể làm:

>>> escaped_str = '"Hello,\\nworld!"'
>>> raw_str = eval(escaped_str)
>>> print raw_str
Hello,
world!
>>> 

Tuy nhiên, điều đó liên quan đến việc chuyển một chuỗi (có thể không đáng tin cậy) đến eval () là một rủi ro bảo mật. Có hàm nào trong lib chuẩn nhận một chuỗi và tạo ra một chuỗi không có hàm ý bảo mật không?

Câu trả lời:


137
>>> print '"Hello,\\nworld!"'.decode('string_escape')
"Hello,
world!"

9
Có cái gì đó tương thích với python 3 không?
thejinx0r

3
@ thejinx0r: hãy xem qua đây: stackoverflow.com/questions/14820429/…
ChristopheD

29
Về cơ bản cho Python3 bạn muốnprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD

3
Đối với python 3, sử dụngvalue.encode('utf-8').decode('unicode_escape')
Casey Kuball

8
CẢNH BÁO: value.encode('utf-8').decode('unicode_escape') làm hỏng các ký tự không phải ASCII trong chuỗi . Trừ khi đầu vào được đảm bảo chỉ chứa các ký tự ASCII, đây không phải là một giải pháp hợp lệ.
Alex Peters

34

Bạn có thể sử dụng ast.literal_evalcái nào an toàn:

Đánh giá an toàn một nút biểu thức hoặc một chuỗi chứa biểu thức Python. Chuỗi hoặc nút được cung cấp chỉ có thể bao gồm các cấu trúc chữ Python sau: chuỗi, số, bộ giá trị, danh sách, dicts, boolean và None. (KẾT THÚC)

Như thế này:

>>> import ast
>>> escaped_str = '"Hello,\\nworld!"'
>>> print ast.literal_eval(escaped_str)
Hello,
world!

3
Có dấu chấm phẩy thoát trong chuỗi sẽ phá vỡ mã này. Ném lỗi cú pháp "ký tự không mong muốn sau ký tự tiếp tục dòng"
darksky

3
thông báo @darksky rằng astthư viện đòi hỏi dấu ngoặc kép (một trong hai "hoặc ', thậm chí """hay ''') xung quanh escaped_str của bạn, vì nó thực sự đang cố gắng chạy nó như (tiêm ngăn chặn chuỗi) mã nhưng tăng cường an ninh Python
InQβ

@ no1xsyzy: Mà trong trường hợp của OP đã là trường hợp rồi; đây là câu trả lời đúng khi strrepra strhoặc bytesobject như trong trường hợp OP; các unicode-escapecâu trả lời codec là khi nó không phải là một repr, nhưng một số hình thức khác của văn bản thoát (không bao quanh bởi dấu ngoặc kép như một phần của dữ liệu chuỗi chính nó).
ShadowRanger

với ký tự utf-8, điều này sẽ không hoạt động. kiểm tra câu trả lời cuối cùng với gói mã. nó thực sự hoạt động.
rubmz

20

Tất cả các câu trả lời đã cho sẽ phá vỡ trên các chuỗi Unicode chung. Những điều sau đây hoạt động cho Python3 trong mọi trường hợp, theo như tôi có thể nói:

from codecs import encode, decode
sample = u'mon€y\\nröcks'
result = decode(encode(sample, 'latin-1', 'backslashreplace'), 'unicode-escape')
print(result)

Như đã nêu trong các nhận xét, bạn cũng có thể sử dụng literal_evalphương thức từ astmô-đun như sau:

import ast
sample = u'mon€y\\nröcks'
print(ast.literal_eval(F'"{sample}"'))

Hoặc như thế này khi chuỗi của bạn thực sự chứa một chuỗi ký tự (bao gồm cả dấu ngoặc kép):

import ast
sample = u'"mon€y\\nröcks"'
print(ast.literal_eval(sample))

Tuy nhiên, nếu bạn không chắc chắn liệu chuỗi nhập liệu có sử dụng dấu ngoặc kép hay đơn làm dấu phân cách hay khi bạn không thể cho rằng nó được thoát đúng cách, thì literal_evalcó thể tăng thêm một SyntaxErrorlúc, phương thức mã hóa / giải mã vẫn hoạt động.


ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"hoạt động tốt với tôi với Python 3.7.3
oldrinb

Cảm ơn nhận xét @oldrinb! Tôi đã chỉnh sửa câu trả lời để bao gồm điều đó.
Jesko Hüttenhain

14

Trong python 3, strcác đối tượng không có decodephương thức và bạn phải sử dụng một bytesđối tượng. Câu trả lời của ChristopheD bao gồm python 2.

# create a `bytes` object from a `str`
my_str = "Hello,\\nworld"
# (pick an encoding suitable for your str, e.g. 'latin1')
my_bytes = my_str.encode("utf-8")

# or directly
my_bytes = b"Hello,\\nworld"

print(my_bytes.decode("unicode_escape"))
# "Hello,
# world"

2
Kết hợp nó với nhau , value.encode('utf-8').decode('unicode_escape').
Casey Kuball

6
Điều này thật đáng buồn sẽ bị
hỏng

Bạn đã thử chọn một mã hóa phù hợp để đánh bóng trong cuộc gọi tới encodechưa?
asac

với ký tự utf-8, điều này sẽ không hoạt động. kiểm tra câu trả lời cuối cùng với gói mã. nó thực sự hoạt động.
rubmz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.