2.19 在替代文本中添加字面文本
问题描述
查找并把任何正则表达式匹配从字面上替换为这8个字符:$%*$11。
解决方案
$%\*$$1\1
替代文本流派:.NET、JavaScript
\$%\\*\$1\\1
替代文本流派:Java
$%\*\$1\\1
替代文本流派:PHP
\$%\*\$1\\1
替代文本流派:Perl
$%\*$1\\1
替代文本流派:Python、Ruby
讨论
在替代文本中转义字符的时机和方式
这个实例显示了各种替代文本流派中使用的不同转义规则。在替代文本中,你可能会需要转义的两个字符是美元符号($)和反斜杠()。而它们所使用的转义字符也分别是美元符号和反斜杠。
在这个例子中的百分号(%)和星号(*)总是字面字符,然而一个前导的反斜杠也可能会被当作一个转义字符,而不是一个字面上的反斜杠。«$1»和/或«1»是指向一个捕获分组的反向引用。实例2.21中会讲解哪些流派对于反向引用会使用哪种语法。这个题目对于我们讲到的7种替代文本流派就存在了5种解决方案,这个事实也说明,关于替代文本的语法,根本就没什么标准。
.NET和JavaScript
.NET和JavaScript总是把反斜杠当作一个字面字符。不需要再用另外一个反斜杠来对它进行转义,否则就会在替换中得到两个反斜杠。
单个出现的美元符号也是一个字面字符。只有当它们之后是数字、&、反引号、垂直引号、下划线、加号或者另外一个美元符号的时候,才需要被转义。要转义美元符号,需要在它前面再加一个美元符号。
如果你觉得这样会读起来更加清晰,也可以选择把所有的美元符号都用两个来表示。下面这个解答也是同样正确的:
$$%\*$$1\1
替代文本流派:.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或者另外一个正则测试工具来测试查找和替换命令,那么在这个实例中给出的替代文本也同样会给出所期望的结果。
但是如果你把它们直接粘贴到源代码中,在两边放上引号字符,那么这些同样的替代文本并不能正常使用。编程语言中的字符串文本拥有它们自己的转义规则,因此你需要在替代文本的转义规则之上再遵循这些转义规则才行。最终你所得到的很可能会是一堆混杂的反斜杠。