本節書摘來自異步社群《正規表達式經典執行個體(第2版)》一書中的第2章,第2.19節,作者: 【美】jan goyvaerts , steven levithan著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
問題描述
查找并把任何正規表達式比對從字面上替換為這8個字元:$%*$11。
解決方案
讨論
在替代文本中轉義字元的時機和方式
這個執行個體顯示了各種替代文本流派中使用的不同轉義規則。在替代文本中,你可能會需要轉義的兩個字元是美元符号($)和反斜杠()。而它們所使用的轉義字元也分别是美元符号和反斜杠。
在這個例子中的百分号(%)和星号(*)總是字面字元,然而一個前導的反斜杠也可能會被當作一個轉義字元,而不是一個字面上的反斜杠。«$1»和/或«1»是指向一個捕獲分組的反向引用。執行個體2.21中會講解哪些流派對于反向引用會使用哪種文法。這個題目對于我們講到的7種替代文本流派就存在了5種解決方案,這個事實也說明,關于替代文本的文法,根本就沒什麼标準。
.net和javascript
.net和javascript總是把反斜杠當作一個字面字元。不需要再用另外一個反斜杠來對它進行轉義,否則就會在替換中得到兩個反斜杠。
單個出現的美元符号也是一個字面字元。隻有當它們之後是數字、&、反引号、垂直引号、下劃線、加号或者另外一個美元符号的時候,才需要被轉義。要轉義美元符号,需要在它前面再加一個美元符号。
如果你覺得這樣會讀起來更加清晰,也可以選擇把所有的美元符号都用兩個來表示。下面這個解答也是同樣正确的:
.net和xregexp還要求對後面跟着一個起始花括号的美元符号進行轉義。在.net中,«${group}»是一個命名反向引用。标準javascript中沒有使用xregexp庫時則不支援命名反向引用。
java
在java中,反斜杠用來在替代文本中轉義反斜杠和美元符号。所有字面的反斜杠和所有字面的美元符号都必須轉義。如果你不轉義它們,java就會抛出一個異常。
php
php要求後面跟數字的反斜杠、後面跟數字或者起始花括号的美元符号,都需要使用反斜杠來進行轉義。
反斜杠也可以對另外一個反斜杠進行轉義。是以,你需要使用«\»來在替換文本中表示兩個字面上的反斜杠。所有其他的反斜杠都被認為是字面上的反斜杠。
perl
perl與其他替代文本流派都有些不同:它其實不能歸屬到任何一種替代文本流派。雖然其他程式設計語言都在查找和替換過程中使用一些特殊邏輯進行替換,比如«$1»,然而perl中這隻是正常的變量插值(interpolation)。在替代文本中,需要對所有字面上的美元符号用反斜杠進行轉義,就像在任意雙引号字元串中一樣。
一個例外是perl同樣支援反向引用的«1»文法。是以,如果你需要字面上的反斜杠後跟數字,則需要對反斜杠進行轉義。為了避免反斜杠對美元符号進行轉義,是以需要對後面跟着美元符号的反斜杠進行轉義。
反斜杠也可以轉義另外一個反斜杠。是以,你需要使用«\»來在替換文本中表示兩個字面上的反斜杠。所有其他的反斜杠都視為字面上的反斜杠。
python和ruby
美元符号在python和ruby的替代文本中并不擁有特殊含義。如果反斜杠後面跟着一個會給反斜杠賦予特殊含義的字元,那麼這個反斜杠就需要使用另外一個反斜杠進行轉義。
在python中,«1»~«9»,以及«g<»會建立反向引用。是以這些反斜杠就需要進行轉義。
在ruby中,你需要對後面跟着數字、&、反引号、垂直引号或者加号的反斜杠進行轉義。
在這兩種語言中,反斜杠都可以轉義另外一個反斜杠。是以,你需要使用«\»在替換文本中表示兩個字面上的反斜杠。所有其他的反斜杠都視為字面上的反斜杠。
更多關于字元串字面量的轉義規則
記住在本章中,我們關心的隻是正規表達式和替代文本自身。下一章會講解程式設計語言和字元串字面量的内容。
上述替代文本作為實際字元串變量直接傳遞給replace()函數是可以正常工作的。換句話說,如果你在應用程式中給使用者提供一個文本框,讓使用者輸入替代文本,那麼這些解決方案所給出的文本,正是使用者為了讓查找和替換正常工作所需要輸入的内容。如果你使用regexbuddy或者另外一個正則測試工具來測試查找和替換指令,那麼在這個執行個體中給出的替代文本也同樣會給出所期望的結果。
但是如果你把它們直接粘貼到源代碼中,在兩邊放上引号字元,那麼這些同樣的替代文本并不能正常使用。程式設計語言中的字元串文本擁有它們自己的轉義規則,是以你需要在替代文本的轉義規則之上再遵循這些轉義規則才行。最終你所得到的很可能會是一堆混雜的反斜杠。