![](/img/trans.png)
[英]Handling backreferences to capturing groups in re.sub replacement pattern
[英]Python re.sub: ignore backreferences in the replacement string
我想用字符串替換模式。 字符串以變量形式給出。 它當然可能包含'\\ 1',它不應該被解釋為反向引用 - 而只是作為\\ 1。
我怎樣才能做到這一點?
使用re.escape()
的上一個答案會逃避太多,並且在替換和替換的字符串中會出現不需要的反斜杠。
看起來在Python中只有反斜杠需要在替換字符串中轉義,因此這樣的事情就足夠了:
replacement = replacement.replace("\\", "\\\\")
示例 :
import re
x = r'hai! \1 <ops> $1 \' \x \\'
print "want to see: "
print x
print "getting: "
print re.sub(".(.).", x, "###")
print "over escaped: "
print re.sub(".(.).", re.escape(x), "###")
print "could work: "
print re.sub(".(.).", x.replace("\\", "\\\\"), "###")
輸出:
want to see:
hai! \1 <ops> $1 \' \x \\
getting:
hai! # <ops> $1 \' \x \
over escaped:
hai\!\ \1\ \<ops\>\ \$1\ \\'\ \x\ \\
could work:
hai! \1 <ops> $1 \' \x \\
由於評論,我想了很久,並試了一下。 幫助我增加了對逃避的理解,所以我幾乎完全改變了我的答案,它可能對以后的讀者有用。
NullUserException為您提供了簡短的版本,我試着再解釋一下。 由於對Qtax和Duncan的批評性評論,這個答案現在是正確和有用的。
反斜杠具有特殊含義,它是字符串中的轉義字符,這意味着反斜杠和后面的字符形成一個轉義序列,當使用字符串完成某些操作時轉換為其他內容。 這個“完成的東西”已經是字符串的創建。 因此,如果你想使用\\
字面意思,你需要逃避它。 這個轉義字符就是反斜杠本身。
因此,開始一些例子,以便更好地了解會發生什么。 我另外打印字符串中字符的ASCII碼,以期增加對所發生情況的理解。
s = "A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
正在印刷
A
B
['A', '\x01', '\n', 'B']
['0x41', '0x1', '0xa', '0x42']
因此,當我在代碼中鍵入\\
和1
時, s
不包含這兩個字符,它包含ASCII字符0x01
,即“標題的開頭”。 對於\\n
,它相同,它將換行符轉換為0x0a
。
由於並不總是需要此行為,因此可以使用原始字符串,其中將忽略轉義序列。
s = r"A\1\nB"
print s
print [x for x in s]
print [hex(ord(x)) for x in s]
我剛剛在字符串之前添加了r
,結果就是現在
A\1\nB
['A', '\\', '1', '\\', 'n', 'B']
['0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42']
所有字符都是在我輸入時打印的。
這就是我們的情況。 現在還有下一件事。
可能存在這樣的情況:應該將字符串傳遞給正則表達式,因此在正則表達式中具有特殊含義的每個字符(例如+ * $ [。)都需要轉義,因此有一個特殊的函數re.escape
做這項工作。
但是對於這個問題,這是一個錯誤的函數,因為字符串不應該在正則表達式中使用,而是作為re.sub
的替換字符串。
所以新情況:
包含轉義序列的原始字符串應該用作re.sub
替換字符串。 re.sub
還將處理轉義序列,但與之前的處理有一個小的但重要的區別: \\n
仍然被轉換為0x0a
的換行符,但是\\1
的轉換現在已經改變了! 它將被re.sub
則表達式的捕獲組1的內容替換。
s = r"A\1\nB"
print re.sub(r"(Replace)" ,s , "1 Replace 2")
結果是
1 AReplace
B 2
\\1
已替換為捕獲組的內容, \\n
替換為LineFeed字符。
重要的是,你必須了解這種行為,現在你有兩種可能性(我不會判斷哪一種是正確的)
創建者不確定字符串行為,如果他輸入\\n
那么他想要一個換行符。 在這種情況下,使用它來逃避\\
后面跟一個數字。
OnlyDigits = re.sub(r"(Replace)" ,re.sub(r"(\\\\)(?=\\d)", r"\\\\\\\\", s) , "1 Replace 2") print OnlyDigits print [x for x in OnlyDigits] print [hex(ord(x)) for x in OnlyDigits
輸出:
1 A\\1 B 2 ['1', ' ', 'A', '\\\\', '1', '\\n', 'B', ' ', '2'] ['0x31', '0x20', '0x41', '0x5c', '0x31', '0xa', '0x42', '0x20', '0x32']
創作者確切地知道他在做什么,如果他想要換行,他就會輸入\\0xa
。 在這種情況下逃避所有
All = re.sub(r"(Replace)" ,re.sub(r"(\\\\)", r"\\\\\\\\", s) , "1 Replace 2") print All print [x for x in All] print [hex(ord(x)) for x in All]
輸出:
1 A\\1\\nB 2 ['1', ' ', 'A', '\\\\', '1', '\\\\', 'n', 'B', ' ', '2'] ['0x31', '0x20', '0x41', '0x5c', '0x31', '0x5c', '0x6e', '0x42', '0x20', '0x32']
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.