簡體   English   中英

Python re.sub:忽略替換字符串中的反向引用

[英]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字符。

重要的是,你必須了解這種行為,現在你有兩種可能性(我不會判斷哪一種是正確的)

  1. 創建者不確定字符串行為,如果他輸入\\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'] 
  2. 創作者確切地知道他在做什么,如果他想要換行,他就會輸入\\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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM