在正则表达式中,匹配字符串的末尾或特定字符

我有根绳子。末端不同,如 index.php?test=1&list=ULindex.php?list=UL&more=1。我要找的是 &list=

我怎样才能匹配它,不管它是在字符串的中间还是在字符串的末尾?到目前为止,我已经得到了 [&|\?]list=.*?([&|$]),但是 ([&|$])部分实际上不工作; 我试图使用它来匹配 &或字符串的末尾,但是字符串的末尾不工作,所以这个模式匹配第二个示例,但不匹配第一个示例。

71747 次浏览

用途:

/(&|\?)list=.*?(&|$)/

请注意,当使用方括号表达式时,其中的每个字符(除了 一些异常)都将按照字面意义进行解释。换句话说,[&|$]匹配 角色&|$

简而言之

[...]中的任何零宽度断言都失去了零宽度断言的含义。[\b]不匹配一个单词边界(它匹配一个反向空间,或者,在 POSIX,\或者 b) ,[$]匹配一个字面 $字符,而 [^]要么是一个错误,要么像在 ECMAScript regex 风格中一样,是任何字符。\z\Z\A锚也是如此。

你可以使用以下任何一种模式来解决这个问题:

[&?]list=([^&]*)
[&?]list=(.*?)(?=&|$)
[&?]list=(.*?)(?![^&])

如果您需要检查“绝对的”、明确的字符串结束锚,那么您需要记住这是各种正则表达式的风格,它使用不同的结构表示:

[&?]list=(.*?)(?=&|$)  - OK for ECMA regex (JavaScript, default C++ `std::regex`)
[&?]list=(.*?)(?=&|\z) - OK for .NET, Go, Onigmo (Ruby), Perl, PCRE (PHP, base R), Boost, ICU (R `stringr`), Java/Andorid
[&?]list=(.*?)(?=&|\Z) - OK for Python

字符序列与单个字符或字符串末尾之间的匹配(当前场景)

.*?([YOUR_SINGLE_CHAR_DELIMITER(S)]|$)模式(由若昂 · 席尔瓦推荐)效率相当低,因为正则表达式引擎首先检查出现在惰点模式右侧的模式,只有当它们不匹配时,它才会“扩展”惰点模式。

在这些情况下,建议使用 < em > 否定字符类 (或者 POSIX 演讲中的 括号表达式括号表达式) :

[&?]list=([^&]*)

请参阅演示 . 详细信息

  • [&?]-匹配 &?的正字符类(注意字符类中字符/字符范围之间的关系是 OR 关系)
  • 字符串,字符序列
  • 捕获组 # 1: 除 &([^&])以外的零个或更多(*)字符,尽可能多

检查尾随的单个字符分隔符是否存在,而不返回它或字符串的末尾

大多数正则表达式(包括从 ECMAScript 2018开始的 JavaScript)都支持查找,只有在模式匹配或不匹配时才返回 true 或 false 的结构。它们对于可能以相同字符开始和结束的连续匹配是至关重要的(参见原始模式,它可能匹配以 &开始和结束的字符串)。尽管在查询字符串中不需要它,但它是一种常见的场景。

在这种情况下,您可以使用两种方法:

  • 一个包含正面字符类 (?=[SINGLE_CHAR_DELIMITER(S)]|$)的交替的正面预测
  • 只有一个负字符类的负向前瞻: (?![^SINGLE_CHAR_DELIMITER(S)])

负向前瞻解决方案更有效一些,因为它不包含增加匹配过程复杂性的交替组。OP 解决方案类似于

[&?]list=(.*?)(?=&|$)

或者

[&?]list=(.*?)(?![^&])

参见 这个正则表达式演示这里还有一个

当然,如果后面的分隔符是多个字符序列,那么只有一个正的前瞻解决方案可以工作,因为 [^yes]不会否定一个字符序列,但是类中的字符(即 [^yes]匹配除 yes之外的任何字符)。