这是在Sublime Text 2的Ruby包中的一个片段文件中找到的Perl样式的正则表达式:
/(?:\A|_)([A-Za-z0-9]+)(?:\.rb)?/(?2::\u$1)/g
我知道它将像“some_class.rb”这样的文件名转换为“SomeClass”,但我无法弄清楚这部分的作用:(?2::
。 Sublime Text 2使用boost作为其正则表达式,所以我检查了Boost-Extended Format String Syntax的文档,我发现boost支持格式字符串中的条件(f.inst。(?2(foo):(bar))
),但你永远不需要两个冒号。此外,?2
将指向第二个子表达式,但上面的表达式只匹配一个子表达式。出于这些原因,我不认为这是一个条件表达式。
感谢任何有启发性的答案。
答案 0 :(得分:8)
首先,(?2::\u$1)
替换方的///g
不是 Perl。这是Boost自己的扩展
参考上述文件,它是说,
角色'?'开始一个条件表达式,一般形式是:
?Ntrue-expression:false-expression
其中N是十进制数字。
如果子表达式N匹配,则计算true-expression并将其发送到输出,否则将评估false-expression并将其发送到输出。
基于此,让我们分析一下神秘的(?2::\u$1)
?2
总是为false,因为没有第二个捕获组。:
是true-expression
中的“特殊字符”,表示空字符串
true-expression
不能为空,则第一个:
不被解释为true和false表达式之间的分隔符(对于gory /多汁的细节,请阅读附录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
所以我用这个内容定义了一个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是异常†)
:
)跟在数字后面,则忽略它(即它不被解释为true和false表达式之间的分隔符)。::
)跟在数字后面,true-expression
是一个空字符串(第二个:
是分隔符):::
)跟在数字后面,true-expression
是一个空字符串,false-expression
以字面冒号开头(第二个:
是分隔符)(?2::\u$1)
和\u$1
的等同性的结论仍然有效。 †我说异常,因为\u$1
与$1
相比表现得如此不同(除了捕获的子串的第一个字符之外的所有内容都消失了)
答案 1 :(得分:2)
也许替换字符串中有冒号,例如:\u$1
是替换字符串。