65

我有一个字符串。结尾不同,例如index.php?test=1&list=ULor index.php?list=UL&more=1。我正在寻找的一件事是&list=

我如何匹配它,无论是在字符串的中间还是在末尾?到目前为止,我得到了[&|\?]list=.*?([&|$]),但该([&|$])部分实际上不起作用;我正在尝试使用它来匹配字符串的任何一个&或结尾,但字符串部分的结尾不起作用,因此此模式与第二个示例匹配,但与第一个不匹配。

4

2 回答 2

88

利用:

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

请注意,当您使用方括号表达式时,其中的每个字符(有一些例外)都将按字面意思解释。换句话说,[&|$]匹配字符 &|$

于 2012-08-23T00:49:30.643 回答
15

简而言之

内部的任何零宽度断言[...]都失去了零宽度断言的含义。[\b]不匹配单词边界(它匹配一个退格,或者,在 POSIX 中,\或者b),[$]匹配一个文字$字符,[^]或者是一个错误,或者,在 ECMAScript 正则表达式风格中,任何字符。与\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)]|$)模式(由 João Silva 建议)效率相当低,因为正则表达式引擎首先检查出现在惰性点模式右侧的模式,并且只有当它们不匹配时,它才会“扩展”惰性点模式。

在这些情况下,建议使用否定字符类(或POSIX 谈话中的括号表达式):

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

见演示细节

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

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

大多数正则表达式风格(包括从 ECMAScript 2018 开始的 JavaScript)支持环视,即仅在模式匹配或不匹配时才返回 true 或 false 的构造。在预期可能以相同字符开头和结尾的连续匹配时,它们至关重要(请参阅原始模式,它可能匹配以 开头和结尾的字符串&)。尽管在查询字符串中不应该出现这种情况,但这是一种常见的情况。

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

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

负前瞻解决方案效率更高一些,因为它不包含增加匹配过程复杂性的交替组。OP 解决方案看起来像

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

或者

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

在这里查看这个正则表达式演示另一个

当然,如果尾随定界符是多字符序列,则只有肯定的前瞻解决方案才会起作用,因为[^yes]它不会否​​定字符序列,而是会否定类中的字符(即[^yes]匹配除y,e和之外的任何字符s)。

于 2018-07-02T11:08:47.140 回答