Terkadang ketika saya mendapatkan input dari file atau pengguna, saya mendapatkan string dengan urutan escape di dalamnya. Saya ingin memproses urutan escape dengan cara yang sama seperti proses Python melarikan diri urutan dalam string literal .
Misalnya, myString
didefinisikan sebagai:
>>> myString = "spam\\neggs"
>>> print(myString)
spam\neggs
Saya menginginkan fungsi (saya akan menyebutnya process
) yang melakukan ini:
>>> print(process(myString))
spam
eggs
Penting agar fungsi tersebut dapat memproses semua urutan escape dengan Python (tercantum dalam tabel di tautan di atas).
Apakah Python memiliki fungsi untuk melakukan ini?
'spam'+"eggs"+'''some'''+"""more"""
diproses?myString = "'spam'+\"eggs\"+'''some'''+\"\"\"more\"\"\""
,print(bytes(myString, "utf-8").decode("unicode_escape"))
sepertinya berhasil.Jawaban:
Hal yang benar untuk dilakukan adalah menggunakan kode 'string-escape' untuk memecahkan kode string.
Jangan gunakan AST atau eval. Menggunakan codec string jauh lebih aman.
sumber
'string\W+escape'
Notice that spelling alternatives that only differ in case or use a hyphen instead of an underscore are also valid aliases; therefore, e.g. 'utf-8' is a valid alias for the 'utf_8' codec.
>>> print("juancarlo\\tañez".encode('utf-8').decode('unicode_escape'))
Anda mendapatkan:juancarlo añez
latin1
diasumsikan olehunicode_escape
, ulangi bit encode / decode, misalnyas.encode('utf-8').decode('unicode_escape').encode('latin1').decode('utf8')
unicode_escape
tidak berfungsi secara umumTernyata solusi
string_escape
atauunicode_escape
tidak berfungsi secara umum - terutama, tidak berfungsi dengan adanya Unicode yang sebenarnya.Jika Anda dapat yakin bahwa setiap karakter non-ASCII akan di-escape (dan ingat, apa pun di luar 128 karakter pertama adalah non-ASCII),
unicode_escape
akan melakukan hal yang benar untuk Anda. Tetapi jika sudah ada karakter non-ASCII literal dalam string Anda, semuanya akan salah.unicode_escape
pada dasarnya dirancang untuk mengubah byte menjadi teks Unicode. Tetapi di banyak tempat - misalnya, kode sumber Python - data sumber sudah berupa teks Unicode.Satu-satunya cara ini dapat bekerja dengan benar adalah jika Anda mengenkode teks menjadi byte terlebih dahulu. UTF-8 adalah pengkodean yang masuk akal untuk semua teks, sehingga seharusnya berfungsi, bukan?
Contoh berikut ada di Python 3, sehingga literal string lebih bersih, tetapi masalah yang sama ada dengan manifestasi yang sedikit berbeda pada Python 2 dan 3.
Itu salah.
Cara baru yang disarankan untuk menggunakan codec yang mendekode teks menjadi teks adalah dengan memanggil
codecs.decode
secara langsung. Apakah itu membantu?Tidak semuanya. (Juga, di atas adalah UnicodeError pada Python 2.)
The
unicode_escape
codec, meskipun namanya, ternyata menganggap bahwa semua byte non-ASCII berada di Latin-1 (ISO-8859-1) encoding. Jadi, Anda harus melakukannya seperti ini:Tapi itu mengerikan. Ini membatasi Anda pada 256 karakter Latin-1, seolah Unicode belum pernah ditemukan sama sekali!
Menambahkan ekspresi reguler untuk menyelesaikan masalah
(Anehnya, sekarang kami tidak memiliki dua masalah.)
Yang perlu kita lakukan hanyalah menerapkan
unicode_escape
decoder ke hal-hal yang kita yakini teks ASCII. Secara khusus, kami dapat memastikan hanya untuk menerapkannya ke urutan escape Python yang valid, yang dijamin menjadi teks ASCII.Rencananya, kita akan menemukan escape sequence menggunakan regular expression, dan menggunakan fungsi sebagai argumen
re.sub
untuk menggantinya dengan nilai unescaped.Dan dengan itu:
sumber
os.sep
sama sekali? Saya mencoba melakukan ini:patt = '^' + self.prefix + os.sep ; name = sub(decode_escapes(patt), '', name)
dan tidak berhasil. Titik koma ada di sana sebagai pengganti baris baru.os.sep
?) Jika Anda memiliki urutan escape dengan garis miring terbalik di nama direktori Windows Anda, situasinya tidak dapat dipulihkan.Jawaban yang benar dan nyaman untuk python 3:
Rincian tentang
codecs.escape_decode
:codecs.escape_decode
adalah decoder byte-ke-bytecodecs.escape_decode
mendekode urutan escape ascii, seperti:b"\\n"
->b"\n"
,b"\\xce"
->b"\xce"
.codecs.escape_decode
tidak peduli atau perlu mengetahui tentang pengkodean objek byte, tetapi pengkodean byte yang lolos harus cocok dengan pengkodean sisa objek.Latar Belakang:
unicode_escape
adalah solusi yang salah untuk python3. Ini karenaunicode_escape
mendekode byte yang lolos, kemudian mendekode byte ke string unicode, tetapi tidak menerima informasi mengenai codec mana yang akan digunakan untuk operasi kedua.codecs.escape_decode
dari jawaban ini untuk "bagaimana saya .decode ('string-escape') di Python3?" . Seperti yang dinyatakan oleh jawaban tersebut, fungsi tersebut saat ini tidak didokumentasikan untuk python 3.sumber
\x
dari byte UTF-8. Tetapi karena ia mendekode byte menjadi byte, ia tidak - dan tidak dapat - mendekode pelarian apa pun dari karakter Unicode non-ASCII, seperti\u
pelarian.The
ast.literal_eval
Fungsi datang dekat, tetapi akan mengharapkan string akan benar dikutip pertama.Tentu saja interpretasi Python untuk pelolosan garis miring terbalik bergantung pada bagaimana string dikutip (
""
vsr""
vsu""
, tanda kutip tiga, dll) sehingga Anda mungkin ingin memasukkan masukan pengguna dalam tanda kutip yang sesuai dan meneruskan keliteral_eval
. Membungkusnya dalam tanda kutip juga akan mencegahliteral_eval
pengembalian angka, tupel, kamus, dll.Hal-hal mungkin masih rumit jika pengguna mengetikkan tanda kutip dari jenis yang ingin Anda bungkus di sekitar string.
sumber
myString = "\"\ndoBadStuff()\n\""
,print(ast.literal_eval('"' + myString + '"'))
tampaknya mencoba untuk menjalankan kode. Bagaimana bisaast.literal_eval
berbeda / lebih aman darieval
?literal_eval
tidak pernah menjalankan kode. Dari dokumentasi, "Ini dapat digunakan untuk mengevaluasi string yang berisi ekspresi Python dari sumber yang tidak tepercaya tanpa perlu mengurai nilainya sendiri."Ini adalah cara yang buruk untuk melakukannya, tetapi berhasil bagi saya ketika mencoba menafsirkan oktal yang lolos yang diteruskan dalam argumen string.
Perlu disebutkan bahwa ada perbedaan antara eval dan ast.literal_eval (eval jauh lebih tidak aman). Lihat Menggunakan python's eval () vs. ast.literal_eval ()?
sumber
Kode di bawah ini harus berfungsi karena \ n diperlukan untuk ditampilkan pada string.
sumber
replace
tidak melakukan apa-apa), menggunakan API yang sangat usang (string
fungsi modul semacam ini tidak digunakan lagi pada Python 2.0, diganti denganstr
metode, dan hilang sepenuhnya dengan Python 3), dan hanya menangani kasus khusus untuk mengganti satu baris baru, bukan pemrosesan pelolosan umum.