19

我有这个正则表达式:

^(^?)*\?(.*)$

如果我理解正确,这是它所做的细分:

  • ^ - 从字符串的开头开始匹配
  • (^?)* - 我不知道,但它以 1 美元的价格存储
  • \? - 匹配一个问号
  • (.*)$ - 匹配直到字符串结尾的任何内容

那么 (^?)* 是什么意思呢?

4

4 回答 4

22

只是在(^?)寻找文字字符^。正则表达式模式中的^字符仅在用作模式的第一个字符或分组匹配中的第一个字符时才具有特殊含义[]。当在这 2 个位置之外使用时,它的^字面意思是在^输入字符串中查找字符

注意:^第一个和分组位置之外是否按字面解释是正则表达式引擎特定的。我对LUA不够熟悉,无法说明它的作用

于 2013-03-04T16:17:32.490 回答
7

Lua 没有传统的正则表达式语言,它有 Lua 模式。虽然它们看起来很像正则表达式,但 Lua 模式是一种独特的语言,它有一套更简单的规则,最重要的是缺乏分组和交替特性。

解释为 Lua 模式,该示例将使长期使用正则表达式的用户感到惊讶,因为许多细节都不同。

Lua 模式PiL中进行了描述 ,乍一看,它与传统的正则表达式非常相似,足以引起混淆。最大的区别可能是缺少交替运算符,括号仅用于标记捕获,量词(、、、和)仅适用于字符或字符类,而不是转义字符。这个例子可能没有考虑到 Lua 编写的一个重要线索是缺少应用于模式字符串中的任何(或理想情况下,所有)非字母数字字符的 Lua 模式引用字符,并且可疑使用哪些气味像传统的正则表达式来匹配单个文字。 |?-+*%\%\??

对所问问题的简单回答是:(^?)*不是推荐的形式,并且会匹配^*or *,捕获插入符号的存在或不存在。如果那是预期的效果,那么我会写它(%^?)%*以使其更清楚。

要了解为什么会出现这种情况,让我们以给出的模式并将其作为 Lua 模式进行分析。整个模式是:

^(^?)*\?(.*)$

交给string.match(),它会被解释为:

^将匹配锚定到字符串的开头。

(标志着第一次捕获的开始。

^不在模式或字符类的开头,因此它匹配文字^字符。为了清楚起见,可能应该写成%^.

?完全匹配前一个字符的零个或一个。

)标志着第一次捕获的结束。

*不是在可以量化的东西之后,因此它与文字*字符匹配。为了清楚起见,可能应该写成%*.

\在模式匹配自身时,它不是模式语言中的转义字符。但是,它Lua 短字符串文字中的转义字符,使得后面的字符对于字符串文字解析器来说不是特殊的,在这种情况下它是没有实际意义的,因为后面的?在任何情况下都不是特殊的。因此,如果模式用双引号或单引号括起来,那么\将被字符串解析所吸收。如果写成长字符串(如[[^(^?)*\?(.*)$]],反斜杠将在字符串解析器中保留下来,以出现在模式中。

?完全匹配前一个字符的零个或一个。

(标志着第二次捕获的开始。

.完全匹配任何字符,实际上是类的同义词[\000-\255](请记住,在 Lua 中,数字转义是十进制而不是 C 中的八进制)。

*贪婪地匹配零个或多个前一个字符。

)标志着第二次捕获的结束。

$将模式锚定到字符串的末尾。

因此,它匹配并捕获^字符串开头的可选项,然后是*,然后\是未捕获的可选项,并捕获字符串的整个其余部分。string.match将返回两个字符串成功(其中一个或两个都可能是零长度),或nil失败。

编辑:我已经修正了一些错别字,并纠正了我的答案中的一个错误, Egor在评论中注意到了这一点。我忘记了在模式中,特殊符号在无法应用的地方失去了它们的特殊性。这使得第一个星号匹配文字星号而不是错误。大部分答案都是级联的。

请注意,如果您真的想要在 Lua 中使用真正的正则表达式,可以使用一些库来提供它。也就是说,内置的模式语言非常强大。如果这还不够,那么您最好采用完整的解析器,并使用LPeg,它可以完成正则表达式所能做的一切,甚至更多。它甚至附带一个模块,该模块提供完整的正则表达式语法,该语法被翻译成 LPeg 语法以供执行。

于 2013-03-04T20:12:27.757 回答
2

在这种情况下,(^?) 指的是前面的字符串“^”,意思是 Jared 所说的文字字符 ^。查看 regexlib 以进行进一步的解密。

满足您的所有正则表达式需求:http ://regexlib.com/CheatSheet.aspx

于 2013-03-04T16:19:52.473 回答
1

在我看来,表达式创建者的意图是匹配问号前的任意数量的 ^,但只想捕获^ 的第一个实例。但是,正如其他人所说,它可能不是一个有效的表达式,具体取决于引擎。

于 2013-03-04T16:25:30.490 回答