9

这是一个 Perl 风格的正则表达式,可以在 Sublime Text 2 的 Ruby 包中的一个片段文件中找到:

/(?:\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将指向第二个子表达式,但上面的表达式只匹配一个子表达式。由于这些原因,我不认为这是一个条件表达式。

感谢您提供任何启发性的答案。

4

2 回答 2

8

首先,(?2::\u$1)替换端的不是///gPerl 。这是 Boost 自己的扩展

参考上述文件,据说,

性格 '?' 开始一个条件表达式,一般形式是:

?Ntrue-expression:false-expression

其中 N 是十进制数字。

如果子表达式 N 匹配,则计算 true-expression 并将其发送到输出,否则计算 false-expression 并将其发送到输出。

基于此,我们来分析一下神秘(?2::\u$1)

  1. ?2总是错误的,因为没有第二个捕获组。
  2. 第一个:是“特殊字符” true-expression,表示空字符串
    • 如果我们假设true-expression不能为空,则第一个:不会解释为真假表达式之间的分隔符(有关血腥/多汁的细节,请阅读附录 D)。
    • 事实上,我们可以放任何我们想要的东西true-expression(只要:中间没有任何地方),因为?2永远不会评估为真。
  3. \u$1false-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

  1. 如果右侧是(?2::\u$1),则返回HelloWorld
  2. 如果右侧是(?2:\u$1),则返回HW
  3. 如果右侧是(?2:$1),则不返回任何内容
  4. 如果右侧是(?2:::\u$1),则返回:Hello:World
  5. 如果右侧是(?1:\u$1),则返回HelloWorld
  6. 如果右侧是(?1::\u$1),则返回HW
  7. 如果右侧是(?1::$1),则不返回任何内容
  8. 如果右侧是(?1:::\u$1)返回HW
  9. 如果右侧是(?1:::$1)什么也不返回
  10. 如果右侧是\u$1,则返回HelloWorld

基于此的一些初步结论(假设案例 2、6、8 是异常情况

  • 如果只有一个冒号 ( :) 跟在数字后面,它会被忽略(即它不会被解释为真表达式和假表达式之间的分隔符)。
  • 如果 2 个冒号 ( ::) 跟在数字后面,true-expression则为空字符串(第二个:是分隔符)
  • 如果 3 个冒号 ( :::) 跟随数字,true-expression则为空字符串,并且false-expression以文字冒号开头(第二个:是分隔符)
  • (?2::\u$1)比较案例 1 和案例 10,我关于和等价的结论\u$1仍然成立。

我说异常是因为与(捕获的子字符串的第一个字符除外)\u$1相比表现如此不同$1

于 2013-06-26T14:41:16.537 回答
2

也许替换字符串中有一个冒号,就像:\u$1替换字符串一样。

于 2013-06-26T13:56:04.567 回答