Ters eğik çizgi kaçış karakterli bir dizeden nasıl çıkılır?


101

Başka bir dizenin ters eğik çizgiden kaçan bir sürümü olan bir dizem olduğunu varsayalım. Python'da dizenin dışına çıkmanın kolay bir yolu var mı? Örneğin şunları yapabilirim:

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

Ancak bu, bir güvenlik riski olan eval () öğesine (muhtemelen güvenilmeyen) bir dizeyi iletmeyi içerir. Standart kitaplıkta bir dizge alan ve hiçbir güvenlik etkisi olmayan bir dizge üreten bir işlev var mı?

Yanıtlar:


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

9
Python 3 ile uyumlu bir şey var mı?
thejinx0r

3
@ thejinx0r: buraya bir göz atın: stackoverflow.com/questions/14820429/…
ChristopheD

30
Temelde Python3 için istediğinizprint(b"Hello,\nworld!".decode('unicode_escape'))
ChristopheD

3
Python 3 için şunu kullanınvalue.encode('utf-8').decode('unicode_escape')
Casey Kuball

8
UYARI: value.encode('utf-8').decode('unicode_escape') dizedeki ASCII olmayan karakterleri bozar . Girişin yalnızca ASCII karakterleri içermesi garanti edilmedikçe, bu geçerli bir çözüm değildir.
Alex Peters

35

ast.literal_evalGüvenli olanı kullanabilirsiniz :

Bir Python ifadesi içeren bir ifade düğümünü veya bir dizeyi güvenle değerlendirin. Sağlanan dize veya düğüm yalnızca şu Python değişmez yapılarından oluşabilir: dizeler, sayılar, tuples, listeler, diktler, mantıksallar ve Yok. (SON)

Bunun gibi:

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

3
Dizede kaçan noktalı virgül bulunması bu kodu bozar. Bir sözdizimi hatası "satır devam karakterinden sonra beklenmeyen karakter"
atıyor

3
@darksky, astkitaplığın , aslında Python kodu olarak çalıştırmaya çalıştığı, ancak güvenliği artırdığı (dizgi enjeksiyonunu önlediği) için escaped_str'in etrafında tırnak işaretleri (ya "da ', hatta """ya da ''') gerektirdiğini fark etti
InQβ

@ no1xsyzy: OP'nin durumunda zaten durum böyle; Bu Doğru cevap strbir olan repra strveya bytesOP'ın durumunda olduğu gibi nesne; unicode-escapecodec'i cevabım değil bir zaman içindir repr, ancak kaçan metnin diğer bazı formu (dize verileri kendisi bir parçası olarak tırnak içine değil).
ShadowRanger

utf-8 karakterleri ile bu çalışmayacaktır. kod paketi ile son cevabı kontrol edin. aslında çalışıyor.
rubmz

FWIW Bazı kaçmış JSON metnini ayrıştırmaya çalışıyordum ve bu hatayı almaya devam ettim [ERROR] TypeError: string indices must be integersve bu çözüm bunu çözmek için çalıştı. Dizenin görünümünü kaldırın, ardından JSON olarak ayrıştırın.
cyber-monk

20

Verilen tüm yanıtlar genel Unicode dizelerinde kırılır. Aşağıdakiler, anlayabildiğim kadarıyla her durumda Python3 için çalışıyor:

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

Yorumlarda belirtildiği gibi , literal_evalyöntemi astmodülden de şu şekilde kullanabilirsiniz:

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

Veya dizeniz gerçekten bir dize değeri içerdiğinde (tırnak işaretleri dahil) şöyle:

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

Eğer düzgün hiç kaçmış olması kabul edemeyiz zaman girdi dizesi sınırlayıcı olarak çift veya tek tırnak kullanır, yoksa belirsiz Ancak, daha sonra literal_evalbir zam olabilir SyntaxErroriken kodlama / kod çözme yöntemi olacak hala işi.


ast.literal_eval('"mon€y\\nröcks"') == "mon€y\nröcks"Python 3.7.3 ile benim için iyi çalışıyor
oldrinb

@Oldrinb yorumunuz için teşekkürler! Cevabı bunu içerecek şekilde düzenledim.
Jesko Hüttenhain

14

Python 3'te strnesnelerin bir decodeyöntemi yoktur ve bir bytesnesne kullanmanız gerekir . ChristopheD'nin cevabı python 2'yi kapsıyor.

# 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
Bir araya getirmek value.encode('utf-8').decode('unicode_escape'),.
Casey Kuball

6
Eğer dizge bazı utf-8 olmayan ascii karakterleri içeriyorsa (yani lehçe karakterleri)
Pax0r

Çağrıda lehçe için uygun bir kodlama seçmeyi denediniz encodemi?
asac

utf-8 karakterleri ile bu çalışmayacaktır. kod paketi ile son cevabı kontrol edin. aslında çalışıyor.
rubmz
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.