用于从 url /xx/xx 两组中获取区域和语言的正则表达式
Regex for getting region and lang from url /xx/xx in two groups
我有一个 url 结构,其中第一个子目录是区域,然后第二个可选的是语言覆盖:
https://example.com/no/en
我正在尝试将这两个部分分别放在一个组中。这样,在 JS 中,我可以执行以下操作来获取 url:
的每个部分
const pathname = window.location.pathname // '/no/en/mypage'
const match = pathname.match('xxx')
const region = match[1] // 'no' or '/no'
const language = match[2] // 'en' or '/en'
我曾尝试创建多个正则表达式,但没有成功满足以下所有要求:
这是我最接近的一次,但由于还将 /donotmatch
中的“/do”与以下正则表达式匹配,因此很容易出错:
(\/[a-z]{2})(\/[a-z]{2})?
这个的问题在于它也匹配 /noada
这样的情况。
然后我尝试匹配前两个 a-z,然后是正斜杠或没有这样的字符:(\/[a-z]{2}\/|[^.])([a-z]{2}\/|[^.])?
我想我没有得到 not 部分的正确语法。
我试图创建的正则表达式必须通过这些标准才能不被破坏:
- /否 - 第 1 组匹配(否),第 2 组未定义
- /否/ - 第 1 组匹配(否),第 2 组未定义
- /nona - 没有匹配项
- /no/en - 第 1 组匹配(否),第 2 组匹配(en)
- /no/en/ - 第 1 组匹配(否),第 2 组匹配(en)
- /no/enen - 第 1 组匹配(否),第 2 组未定义
- /no/en/something - 第 1 组匹配(否),第 2 组匹配(en)
- /no/en/jp - 第 1 组匹配(否),第 2 组匹配(en)(不会匹配 jp)
我觉得我真的很接近一个可行的解决方案,但到目前为止我的所有尝试都略有失败。
如果分组部分不可能,我想也可以得到 /xx/xx 然后按 / 拆分也是一种选择。
在每个捕获后跟上 (?=$|/)
,这是一种前瞻性断言,接下来是输入的结尾或斜杠。
https?://[^/]+/(\w\w)(?=$|/)(?:/(\w\w)(?=$|/))?
第二次捕获通过 (?:…)?
包裹在可选的 non-capture 组中
为了更严格地只允许字母,请将 \w
替换为 [a-z]
,但 \w
可能足以满足您的需要。
您可以将此正则表达式与可选的第二个捕获组一起使用:
\/(\w{2})(?:\/(\w{2}))?(?:\/|$)
正则表达式解释:
\/
: 比赛开始 /
(\w{2})
: 第一个匹配2个单词字符的捕获组
(?:\/(\w{2}))?
:可选的 non-capture 组,以 /
开头,后跟 seconf 捕获组以匹配 2 个单词字符。
(?:\/|$)
:匹配结束 /
或行尾
我刚刚看到使用新 URL pattern API
获得相同结果的新方法
API 在撰写此答案时是相当新的,但是您现在可以使用一个 polyfill 来添加对它的支持。
const pattern = new URLPattern({ pathname: '/:region(\w{2})/:lang(\w{2})?' })
const result = pattern.exec('https://example.com/no/en')?.pathname?.groups
const region = result?.region // no or undefined
const lang = result?.lang // en or undefined
解决尾部斜杠的问题,可以在将“url 字符串”发送到 exec 方法之前将斜杠替换为空。
// ...
const urlWithoutTrailingSlashes = 'https://example.com/no/en/'.replace(/\/+$/, '')
const result = pattern.exec(urlWithoutTrailingSlashes)?.pathname?.groups
// ...
我还没有找到一种方法来在模式内的正则表达式中添加可选的尾部斜杠作为 limitations of lookaheads and ends with。如果有人找到方法,请编辑此答案或添加评论。
我有一个 url 结构,其中第一个子目录是区域,然后第二个可选的是语言覆盖:
https://example.com/no/en
我正在尝试将这两个部分分别放在一个组中。这样,在 JS 中,我可以执行以下操作来获取 url:
的每个部分const pathname = window.location.pathname // '/no/en/mypage'
const match = pathname.match('xxx')
const region = match[1] // 'no' or '/no'
const language = match[2] // 'en' or '/en'
我曾尝试创建多个正则表达式,但没有成功满足以下所有要求:
这是我最接近的一次,但由于还将 /donotmatch
中的“/do”与以下正则表达式匹配,因此很容易出错:
(\/[a-z]{2})(\/[a-z]{2})?
这个的问题在于它也匹配 /noada
这样的情况。
然后我尝试匹配前两个 a-z,然后是正斜杠或没有这样的字符:(\/[a-z]{2}\/|[^.])([a-z]{2}\/|[^.])?
我想我没有得到 not 部分的正确语法。
我试图创建的正则表达式必须通过这些标准才能不被破坏:
- /否 - 第 1 组匹配(否),第 2 组未定义
- /否/ - 第 1 组匹配(否),第 2 组未定义
- /nona - 没有匹配项
- /no/en - 第 1 组匹配(否),第 2 组匹配(en)
- /no/en/ - 第 1 组匹配(否),第 2 组匹配(en)
- /no/enen - 第 1 组匹配(否),第 2 组未定义
- /no/en/something - 第 1 组匹配(否),第 2 组匹配(en)
- /no/en/jp - 第 1 组匹配(否),第 2 组匹配(en)(不会匹配 jp)
我觉得我真的很接近一个可行的解决方案,但到目前为止我的所有尝试都略有失败。
如果分组部分不可能,我想也可以得到 /xx/xx 然后按 / 拆分也是一种选择。
在每个捕获后跟上 (?=$|/)
,这是一种前瞻性断言,接下来是输入的结尾或斜杠。
https?://[^/]+/(\w\w)(?=$|/)(?:/(\w\w)(?=$|/))?
第二次捕获通过 (?:…)?
为了更严格地只允许字母,请将 \w
替换为 [a-z]
,但 \w
可能足以满足您的需要。
您可以将此正则表达式与可选的第二个捕获组一起使用:
\/(\w{2})(?:\/(\w{2}))?(?:\/|$)
正则表达式解释:
\/
: 比赛开始/
(\w{2})
: 第一个匹配2个单词字符的捕获组(?:\/(\w{2}))?
:可选的 non-capture 组,以/
开头,后跟 seconf 捕获组以匹配 2 个单词字符。(?:\/|$)
:匹配结束/
或行尾
我刚刚看到使用新 URL pattern API
获得相同结果的新方法API 在撰写此答案时是相当新的,但是您现在可以使用一个 polyfill 来添加对它的支持。
const pattern = new URLPattern({ pathname: '/:region(\w{2})/:lang(\w{2})?' })
const result = pattern.exec('https://example.com/no/en')?.pathname?.groups
const region = result?.region // no or undefined
const lang = result?.lang // en or undefined
解决尾部斜杠的问题,可以在将“url 字符串”发送到 exec 方法之前将斜杠替换为空。
// ...
const urlWithoutTrailingSlashes = 'https://example.com/no/en/'.replace(/\/+$/, '')
const result = pattern.exec(urlWithoutTrailingSlashes)?.pathname?.groups
// ...
我还没有找到一种方法来在模式内的正则表达式中添加可选的尾部斜杠作为 limitations of lookaheads and ends with。如果有人找到方法,请编辑此答案或添加评论。