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

80

我有一个字符串,结尾是不同的,例如index.php?test=1&list=ULindex.php?list=UL&more=1。我想找到的是&list=

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

2个回答

111

使用:

/(&|\?)list=.*?(&|$)/
请注意,当您使用方括号表达式时,其中的每个字符(有一些例外)都将被解释为文字意义。换句话说,[&|$] 匹配字符 &|$

4
谢谢,我之前不知道方括号需要“逐字解释”的部分。非常有用!那么为了使用 | 分隔两个或多个字符,是否需要使用 () - Gary
1
是的,确实需要将备选项分组(())。 - João Silva
@DrazenBjelovuk 你可能想表达的是'SomeText/blahblah'.match(/Some([^\/]*)/)[1](输出为Text)。请看我的答案,每一个解决方案都包含一个捕获组,用于捕获通常在返回匹配后作为第一组获取所需子匹配。 - Wiktor Stribiżew
看起来我当时的意思是 string.match(/Some.*?(\/|$)/)[0];。不过现在不知道是干什么用的。哈哈。 - Drazen Bjelovuk
@DrazenBjelovuk 是的,懒惰点匹配将匹配到后续子模式的最左出现。 - Wiktor Stribiżew

28

简而言之

[...] 中的任何零宽断言都失去了其零宽断言的含义。[\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

在当前情况下,字符序列与单个字符或字符串结尾的匹配可以使用建议由João Silva提供.*?([YOUR_SINGLE_CHAR_DELIMITER(S)]|$)模式。但该模式效率较低,因为正则表达式引擎首先检查出现在惰性点模式右侧的模式,只有在它们不匹配时才会“展开”惰性点模式。
在这些情况下,建议使用否定字符类(或POSIX讨论中的括号表达式):
[&?]list=([^&]*)

查看演示详情

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

检查是否存在结尾单个字符分隔符而不返回它或字符串结束

大多数正则表达式引擎(包括 ECMAScript 2018 开始的 JavaScript)都支持环视,这些构造仅在模式匹配或不匹配时返回 true 或 false。如果预计有可能出现以相同字符开头和结尾的连续匹配(请参阅原始模式,它可能匹配以 & 开头和结尾的字符串),则这些构造至关重要。虽然在查询字符串中不太可能出现这种情况,但这是一种常见情况。

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

  • 使用带有正向字符类的交替的正向先行断言:(?=[SINGLE_CHAR_DELIMITER(S)]|$)
  • 只使用负向字符类的负向先行断言:(?![^SINGLE_CHAR_DELIMITER(S)])

负向先行断言解决方案稍微更有效,因为它不包含添加匹配过程复杂性的交替组。OP 的解决方案将如下:

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

或者

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

请看这个正则表达式演示这个演示

当然,如果尾随定界符是多字符序列,则仅使用正向先行解决方案才能起作用,因为[^yes]不能否定一系列字符,而是类内的字符(即[^yes]匹配除yes之外的任何字符)。


2
在我看来,这应该是被接受的答案。否定字符解决方案正是所需的,而且更加通用(即,可能适用于其他寻找类似问题的用户)。 - TrustyPatches

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接