【问题标题】:RegEx to match several URL patterns with Javascript正则表达式将多个 URL 模式与 Javascript 匹配
【发布时间】:2020-02-27 08:31:20
【问题描述】:

我正在尝试匹配 Javascript 中的几种 URL 模式中的任何一种。模式是:

  • 首页 - / 后面没有任何内容。
  • 三个解决方案页面之一。每个solutions(number) 后面可以跟一个/ 和后面的任何字符。
    • /solutions/99043/solutions/99043/blah
    • /solutions/60009/solutions/60009/blah
    • /solutions/40117/solutions/40117/blah
  • 搜索:/search 后跟任何字符,例如?blah

我试过的RegEx如下:

/\/$|\/solutions\/(99043|60009|40117)\/.*|\/search.*/

在这个函数中:

(function () {
    const urlPath = window.location.pathname;
    if (urlPath.match(/\/$|\/solutions\/(99043|60009|40117)\/.*|\/search.*/)) {
        console.log("urlPath", urlPath);
    }
})()

它不起作用,因为一切似乎都匹配。有人知道我哪里出错了吗?

根据评论,一个匹配但不应该匹配的 URL 示例: /solutions/

【问题讨论】:

  • 您能否提供一些存在意外行为的测试用例?
  • @Bazza 我已经用一个例子更新了这个问题。

标签: javascript regex url


【解决方案1】:
\/(solutions|search)(\/(99043|60009|40117).*|)

https://regex101.com/r/nqtB4v/2

【讨论】:

  • 也匹配以给定数字开头的数字
  • 点最简单的答案,除了它不处理/(主页)场景。
【解决方案2】:

如果您从 URL 中提取路径名然后执行匹配,我建议使用 ^\/$ 而不是仅匹配“以斜线结尾”。

那就是^\/$|\/solutions\/(99043|60009|40117)\/.*|\/search.*

您可以在 regex101.com 上对其进行测试。我发现正则表达式对于可视化正则表达式非常有帮助。

【讨论】:

    【解决方案3】:

    您可以使用以下正则表达式:

    ^\/((solutions(\/(99043|60009|40117)(\/.*)?)?)|search(.*)?)$
    

    测试:

    var regex = /^\/((solutions(\/(99043|60009|40117)?(\/.*)?)?)|search(.*)?)?$/
    
    console.log(1, regex.test('/')) // true
    
    console.log(2, regex.test('/solutions')) // true
    console.log(3, regex.test('/solutions/')) // true
    
    console.log(4, regex.test('/solutions/99043')) // true
    console.log(5, regex.test('/solutions/99043/')) // true
    console.log(6, regex.test('/solutions/99043/anything')) // true
    
    console.log(7, regex.test('/solutions/60009')) // true
    console.log(8, regex.test('/solutions/60009/')) // true
    console.log(9, regex.test('/solutions/60009/anything')) // true
    
    console.log(10, regex.test('/solutions/40117')) // true
    console.log(11, regex.test('/solutions/40117/')) // true
    console.log(12, regex.test('/solutions/40117/anything')) // true
    
    console.log(13, regex.test('/solutions/00000')) // false
    console.log(14, regex.test('/solutions/00000/')) // false
    console.log(15, regex.test('/solutions/00000/anything')) // false
    
    console.log(16, regex.test('/bug')) // false
    
    console.log(17, regex.test('/search?query=javascript')) // true
    console.log(18, regex.test('/search/?query=javascript')) // true

    所以,这个正则表达式可以防止以下错误:

    • 阻止测试子字符串而不是完整路径名:

    /bug/solutions/99043 // 错误

    • 防止仅测试部分解决方案编号:

    /solutions/990430000 // 错误

    /solutions/000099043 // 错误

    【讨论】:

    • /solutions/ 不能是独立的:它必须后跟提供的三个数字之一。
    【解决方案4】:

    您可以使用锚来断言字符串的开头^ 和结尾$

    匹配 / 并可选择将部分与解后跟 3 个数字匹配,或使用 alternation 匹配搜索部分。

    ^\/(?:solutions\/(?:99043|60009|40117)(?:\/.*)?|search\b.*)?$
    
    • ^ 字符串开始
    • \/匹配/
    • (?:非捕获组
      • solutions\/匹配solutions/
      • (?:99043|60009|40117) 匹配 3 个号码中的 1 个
      • (?:\/.*)? 可以选择匹配 / 和除换行符以外的任何字符 0+ 次
      • |或者
      • search\b.* 匹配搜索后跟不匹配的单词边界,例如 searchhere
    • )?关闭非捕获组并使其可选
    • $ 字符串结束

    Regex demo

    【讨论】:

    • 字符串的^ 开头会导致我的正则表达式由于某种原因而失败,但解决方案或条件中的附加?: 修复了仅/solutions/ 通过的情况。
    • ^ 将模式锚定到字符串的开头,$ 锚定到结尾。在这种情况下,您可以移除锚点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2019-11-28
    • 2017-10-08
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多