首先,(?2::\u$1)
替换端的不是///g
Perl 。这是 Boost 自己的扩展
参考上述文件,据说,
性格 '?' 开始一个条件表达式,一般形式是:
?Ntrue-expression:false-expression
其中 N 是十进制数字。
如果子表达式 N 匹配,则计算 true-expression 并将其发送到输出,否则计算 false-expression 并将其发送到输出。
基于此,我们来分析一下神秘(?2::\u$1)
?2
总是错误的,因为没有第二个捕获组。
- 第一个
:
是“特殊字符” true-expression
,表示空字符串
- 如果我们假设
true-expression
不能为空,则第一个:
不会被解释为真假表达式之间的分隔符(有关血腥/多汁的细节,请阅读附录 D)。
- 事实上,我们可以放任何我们想要的东西
true-expression
(只要:
中间没有任何地方),因为?2
永远不会评估为真。
\u$1
是false-expression
。
把两个和两个放在一起,我要出去说
/(?:\A|_)([A-Za-z0-9]+)(?:\.rb)?/(?2::\u$1)/g
只是这样做的一种混淆方式:
/(?:\A|_)([A-Za-z0-9]+)(?:\.rb)?/\u$1/g
附录 D:Sublime Text 2 中的片段实验
所以我用这个内容定义了一个 Sublime Text 2 片段
<snippet>
<content><![CDATA[
snakecase: ${1:hello_world}
camelcase: ${1/(?:\A|_)([A-Za-z0-9]+)(?:\.rb)?/(?2::\u$1)/g}
]]></content>
<tabTrigger>convert</tabTrigger>
</snippet>
并为替换的右侧使用不同的表达方式。
给定输入hello_world
- 如果右侧是
(?2::\u$1)
,则返回HelloWorld
- 如果右侧是
(?2:\u$1)
,则返回HW
- 如果右侧是
(?2:$1)
,则不返回任何内容
- 如果右侧是
(?2:::\u$1)
,则返回:Hello:World
- 如果右侧是
(?1:\u$1)
,则返回HelloWorld
- 如果右侧是
(?1::\u$1)
,则返回HW
- 如果右侧是
(?1::$1)
,则不返回任何内容
- 如果右侧是
(?1:::\u$1)
返回HW
- 如果右侧是
(?1:::$1)
什么也不返回
- 如果右侧是
\u$1
,则返回HelloWorld
基于此的一些初步结论(假设案例 2、6、8 是异常情况†)
- 如果只有一个冒号 (
:
) 跟在数字后面,它会被忽略(即它不会被解释为真表达式和假表达式之间的分隔符)。
- 如果 2 个冒号 (
::
) 跟在数字后面,true-expression
则为空字符串(第二个:
是分隔符)
- 如果 3 个冒号 (
:::
) 跟随数字,true-expression
则为空字符串,并且false-expression
以文字冒号开头(第二个:
是分隔符)
(?2::\u$1)
比较案例 1 和案例 10,我关于和等价的结论\u$1
仍然成立。
†我说异常是因为与(捕获的子字符串的第一个字符除外)\u$1
相比表现如此不同$1