【问题标题】:What does (^?)* mean in this regex?(^?)* 在这个正则表达式中是什么意思?
【发布时间】:2013-02-18 19:16:17
【问题描述】:

我有这个正则表达式:

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

如果我理解正确,这是它的作用的细分:

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

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

【问题讨论】:

  • 您能指定这里使用的正则表达式引擎吗?
  • @doremi:在我阅读文档之后,Lua 的正则表达式本身就是一个野兽。正则表达式的含义可能会随着 gmatch 或 match 一起使用而改变。
  • 您应该接受 RBerteig 的回答,因为它与 lua 最相关,他更详细地解释了正在发生的事情。
  • Lua 模式看似与正则表达式相似,但不一样

标签: regex lua


【解决方案1】:

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

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

【讨论】:

  • 嗯。我还是不明白。你能给我一个匹配的字符串的例子吗?仅供参考 - 这是在带有查询字符串的 url 上使用的。
  • 不评论(^?)*的无意义?即它是 0 或一个字符匹配,仅匹配字符 ^,匹配 0 到多次 - 与 (^*) 相同(可能),除非正在使用多个组
  • 这可能是一个糟糕的正则表达式,因为它会由其他人提供给我。这就是我试图了解它的作用的部分原因。
  • @AD7six 同意这很可能是假的。 可能对某些正则表达式引擎(例如没有魔法的 Vim)有效,但该设置也会使我的答案无效。很可能是假的,但在我跳出问题的细节之前想知道正则表达式引擎
  • @JaredPar:你的例子很混乱。 .NET 是一个非常糟糕的例子,因为它在你遇到的每一种情况下都有特殊的含义。 Lua 将^ 视为文字字符可能是真的,但让我仔细检查一下。
【解决方案2】:

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

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

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

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

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

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

交给string.match(),会这样解释:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

【讨论】:

  • 其实第一个*不是错误,只是没有魔法。例如,assert(string.match("^*", "^(^?)*"))
  • @EgorSkriptunoff 我认为你是对的。效果大致相同,模式与正则表达式用户认为的不匹配。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2012-05-07
      • 1970-01-01
      • 2017-05-23
      • 2016-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-20
      相关资源
      最近更新 更多