Ucieczka znaków specjalnych wyrażenia regularnego w ciągu znaków Pythona

126

Czy Python ma funkcję, której mogę użyć do zmiany znaczenia znaków specjalnych w wyrażeniu regularnym?

Na przykład I'm "stuck" :\powinien stać się I\'m \"stuck\" :\\.

Wolfy
źródło
2
Co uważasz za postać specjalną?
pafcu
1
Całkowicie zależy od twojego kontekstu. Zwykle te znaki są całkowicie w porządku, gdy masz je wewnątrz łańcucha.
poke
możliwy duplikat Escaping regex string w Pythonie
Jukka Suomela

Odpowiedzi:

197

Posługiwać się re.escape

>>> import re
>>> re.escape(r'\ a.*$')
'\\\\\\ a\\.\\*\\$'
>>> print(re.escape(r'\ a.*$'))
\\\ a\.\*\$
>>> re.escape('www.stackoverflow.com')
'www\\.stackoverflow\\.com'
>>> print(re.escape('www.stackoverflow.com'))
www\.stackoverflow\.com

Powtarzam to tutaj:

re.escape (ciąg)

Zwraca łańcuch z odwrotnym ukośnikiem wszystkich znaków innych niż alfanumeryczne; jest to przydatne, jeśli chcesz dopasować dowolny literał ciągu, który może zawierać metaznaki wyrażenia regularnego.

Od wersji Python 3.7 re.escape()została zmieniona tak, aby zmieniać znaczenie tylko znaków, które mają znaczenie dla operacji regex.

pyfunc
źródło
1
Możesz użyć modułu regex zamiast re. Przykładem może być regex.escape(pattern,string,special_only=True
Lokinou
17

Jestem zaskoczony, że nikt nie wspomniał o używaniu wyrażeń regularnych poprzez re.sub():

import re
print re.sub(r'([\"])',    r'\\\1', 'it\'s "this"')  # it's \"this\"
print re.sub(r"([\'])",    r'\\\1', 'it\'s "this"')  # it\'s "this"
print re.sub(r'([\" \'])', r'\\\1', 'it\'s "this"')  # it\'s\ \"this\"

Ważne uwagi:

  • We wzorcu wyszukiwania uwzględnij \również szukane znaki. Masz zamiar używać \do ucieczki swoje postacie, więc trzeba się uciec , że jak dobrze.
  • Umieść wzorzec wyszukiwania w nawiasach , np. ([\"])Tak, aby wzorzec podstawienia mógł używać znalezionego znaku, gdy dodaje go \przed nim. (To właśnie \1robi: używa wartości pierwszej grupy w nawiasach).
  • rPrzed r'([\"])'środkami jest to surowy ciąg . Nieprzetworzone łańcuchy używają różnych reguł unikania odwrotnych ukośników. Aby pisać ([\"])jako zwykły ciąg, musisz podwoić wszystkie ukośniki odwrotne i napisać '([\\"])'. Nieprzetworzone łańcuchy są bardziej przyjazne, gdy piszesz wyrażenia regularne.
  • We wzorcu podstawiania musisz uciekać, \aby odróżnić go od ukośnika odwrotnego poprzedzającego grupę podstawień, np . \1Stąd r'\\\1'. Aby zapisać to jako zwykły ciąg, potrzebujesz '\\\\\\1'- i nikt tego nie chce.
Tim Ruddick
źródło
9

Użyj repr () [1: -1]. W tym przypadku cudzysłowy nie muszą być znakami ucieczki. Wycinek [-1: 1] służy do usunięcia pojedynczego cudzysłowu z początku i końca.

>>> x = raw_input()
I'm "stuck" :\
>>> print x
I'm "stuck" :\
>>> print repr(x)[1:-1]
I\'m "stuck" :\\

A może po prostu chcesz uciec od frazy, którą chcesz wkleić do swojego programu? Jeśli tak, zrób to:

>>> raw_input()
I'm "stuck" :\
'I\'m "stuck" :\\'
dp_
źródło
3
To nie działa, jeśli łańcuch jest w repr(x)[2:-1]
formacie
W pythonie 3.4, gdzie wszystkie ciągi znaków są w formacie Unicode, niestety nie wydaje się to działać. Zamiast tego print(repr("I'm stuck")[1:-1])drukuje I'm stuck.
dantiston
3

Jak wspomniano powyżej, odpowiedź zależy od Twojego przypadku. Jeśli chcesz zmienić znaczenie łańcucha dla wyrażenia regularnego, powinieneś użyć funkcji re.escape (). Ale jeśli chcesz uciec od określonego zestawu znaków, użyj tej funkcji lambda:

>>> escape = lambda s, escapechar, specialchars: "".join(escapechar + c if c in specialchars or c == escapechar else c for c in s)
>>> s = raw_input()
I'm "stuck" :\
>>> print s
I'm "stuck" :\
>>> print escape(s, "\\", ['"'])
I'm \"stuck\" :\\
spatar
źródło
1

To nie jest takie trudne:

def escapeSpecialCharacters ( text, characters ):
    for character in characters:
        text = text.replace( character, '\\' + character )
    return text

>>> escapeSpecialCharacters( 'I\'m "stuck" :\\', '\'"' )
'I\\\'m \\"stuck\\" :\\'
>>> print( _ )
I\'m \"stuck\" :\
szturchać
źródło
3
Jeśli lewy ukośnik jest jednym z nich, charactersto lepiej, żeby był pierwszym!
steveha
0

Jeśli chcesz zamienić tylko niektóre znaki, możesz użyć tego:

import re

print re.sub(r'([\.\\\+\*\?\[\^\]\$\(\)\{\}\!\<\>\|\:\-])', r'\\\1', "example string.")
Christoph Roeder
źródło