【问题标题】:In regex, match either the end of the string or a specific character在正则表达式中,匹配字符串的结尾或特定字符
【发布时间】:2022-01-06 14:17:13
【问题描述】:

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

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

【问题讨论】:

    标签: regex pattern-matching


    【解决方案1】:

    用途:

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

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

    【讨论】:

    • 谢谢;我不知道方括号的“字面解释”部分。很有用!那么为了使用|分隔两个或多个字符,是否需要()
    • 是的,确实,您需要对备选方案进行分组 (())。
    • @DrazenBjelovuk 你的意思可能是'SomeText/blahblah'.match(/Some([^\/]*)/)[1](输出为Text)。请参阅my answer,每个解决方案都包含一个捕获组,该组捕获所需的子匹配项,您通常会在返回匹配项后将其作为第一个组。
    • @WiktorStribiżew 事后看来,我的意思似乎是string.match(/Some.*?(\/|$)/)[0];。不知道在这一点上做什么虽然大声笑。
    • @DrazenBjelovuk 是的,惰性点匹配将匹配到最左边出现的后续子模式。
    【解决方案2】:

    简而言之

    [...] 中的任何零宽度断言都失去了零宽度断言的含义。 [\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)]|$) 模式 (suggested by João Silva) 效率相当低,因为正则表达式引擎首先检查出现在惰性点模式右侧的模式,并且只有当它们不匹配时才会“扩展”惰性点状图案。

    在这些情况下,建议使用negated character class(或 POSIX 谈话中的 括号表达式):

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

    See demo详情

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

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

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

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

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

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

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

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

    请参阅 this regex demoanother one here

    当然,如果尾随定界符是多字符序列,则只有正向超前解决方案才有效,因为[^yes] 不会否定字符序列,但类中的字符(即[^yes] 匹配除@987654355 之外的任何字符@、es)。

    【讨论】:

    • 这应该是公认的答案,恕我直言,否定字符解决方案正是我们所需要的,而且更通用(即,可能适用于搜索类似问题的其他用户)。
    猜你喜欢
    • 1970-01-01
    相关资源
    最近更新 更多