【问题标题】:What does "(?x::" mean in a Boost regex replacement, where "x" is a number?“(?x::”在 Boost 正则表达式替换中是什么意思,其中“x”是一个数字?
【发布时间】:2013-06-26 13:04:48
【问题描述】:

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

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

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

【问题讨论】:

  • 也许它只是偶然工作?也许第一个:true 部分,第二个: 分隔false 部分。但由于2 不是表达式的一部分,因此条件永远不能使用true 部分,因此它总是使用\u$1(这与您看到的结果一致)。

标签: regex boost sublimetext2


【解决方案1】:

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

参考上述文件,这是saith,

字符“?”开始一个条件表达式,一般形式是:

?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 中的 sn-p 实验

所以我用这个内容定义了一个 Sublime Text 2 sn-p

<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 以文字冒号开头(第二个 : 是分隔符)
  • 比较案例 1 和 10,我对 (?2::\u$1)\u$1 等价的结论仍然成立。

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

【讨论】:

  • 似乎if 部分被简单地贪婪解析(因此最后一个: 标志着truefalse 之间的边界),而不是if 部分不能为空,但只能包含一个 :。但有人必须做一些测试才能弄清楚这一点。
  • 事实上,我只是在 notepad++ 中输入了这个(从版本 6 开始使用 boost),它确实是第一个分隔真假的冒号 - 因此有一个文字 : 包含在替换,肖恩科里一直都是对的。
  • 有趣。好吧,SublimeText 的行为显然与问题相关,但有趣的是,我在 Notepad++ 中得到了完全不同的结果。我想知道这是否是由于不同版本的boost或其他原因。如果有人有时间,直接在 boost 中测试它可能会很有趣。对于 SublimeText,我得出了相同的结论:它使用 (?n:true:false),但如果 \u 在未使用的部分中,则会出现问题。
【解决方案2】:

可能替换字符串中有一个冒号,例如:\u$1 是替换字符串。

【讨论】:

  • 我用 Notepad++(使用 boost)进行了一些测试,看来你是对的。
猜你喜欢
  • 1970-01-01
  • 2013-02-18
  • 2012-06-10
  • 1970-01-01
  • 2011-06-15
  • 2023-03-10
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多