gpt4 book ai didi

javascript - 如何在 Javascript 中使用正则表达式提取可选查询参数

转载 作者:可可西里 更新时间:2023-11-01 02:50:06 25 4
gpt4 key购买 nike

我想构建一个正则表达式来检查“路径”和“foo”参数(非负整数)。 “foo”是可选的。这应该:

匹配

path?foo=67                 # path found, foo = 67
path?foo=67&bar=hello # path found, foo = 67
path?bar=bye&foo=1&baz=12 # path found, foo = 1
path?bar=123 # path found, foo = ''
path # path found, foo = ''

不匹配
path?foo=37signals          # foo is not integer
path?foo=-8 # foo cannot be negative
something?foo=1 # path not found

另外,我想获得 foo 的值,无需执行额外的匹配。

实现这一目标的最简单的正则表达式是什么?

最佳答案

答案

螺丝 你辛苦了,我只想要答案! Okay, here you go ...

var regex = /^path(?:(?=\?)(?:[?&]foo=(\d*)(?=[&#]|$)|(?![?&]foo=)[^#])+)?(?=#|$)/,
URIs = [
'path', // valid!
'pathbreak', // invalid path
'path?foo=123', // valid!
'path?foo=-123', // negative
'invalid?foo=1', // invalid path
'path?foo=123&bar=abc', // valid!
'path?bar=abc&foo=123', // valid!
'path?bar=foo', // valid!
'path?foo', // valid!
'path#anchor', // valid!
'path#foo=bar', // valid!
'path?foo=123#bar', // valid!
'path?foo=123abc', // not an integer
];

for(var i = 0; i < URIs.length; i++) {
var URI = URIs[i],
match = regex.exec(URI);

if(match) {
var foo = match[1] ? match[1] : 'null';
console.log(URI + ' matched, foo = ' + foo);
} else {
console.log(URI + ' is invalid...');
}
}
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>



研究

您的赏金请求要求提供“可靠和/或官方来源”,因此我将引用 RFC on query strings .

The query component contains non-hierarchical data that, along with data in the path component (Section 3.3), serves to identify a resource within the scope of the URI's scheme and naming authority (if any). The query component is indicated by the first question mark ("?") character and terminated by a number sign ("#") character or by the end of the URI.



这似乎是有意为之:查询字符串以第一个 ? 开头。并由 # 终止( anchor 的开始)或 URI 的结尾(在我们的例子中是字符串/行)。他们继续提到大多数数据集都在 key=value 中。对,这就是您期望解析的内容(因此假设是这种情况)。

However, as query components are often used to carry identifying information in the form of "key=value" pairs and one frequently used value is a reference to another URI, it is sometimes better for usability to avoid percent-encoding those characters.



考虑到所有这些,让我们假设一些关于您的 URI 的事情:
  • 您的示例以路径开头,因此路径将从字符串的开头直到 ? (查询字符串), # ( anchor ),或字符串的结尾。
  • 查询字符串是不确定的部分,因为 RFC 并没有真正定义“规范”。浏览器倾向于期望从表单提交中生成查询字符串并且是 key=value 的列表。由 & 附加的对人物。保持这种心态:
  • key 不能是 null , 前面会有 ?& ,并且不能包含 = , &# .
  • 一个值是可选的,前面会加上 key= ,并且不能包含 &# .
  • # 之后的任何内容性格是 anchor 。


  • 让我们开始!

    让我们从 mapping out our basic URI structure 开始.你有一个路径,它是从字符串开始直到 ? 的字符。 , # , 或字符串的结尾。您有一个可选的查询字符串,它以 ? 开头。直到 #或字符串的结尾。你有一个可选的 anchor ,它从 # 开始直到字符串的末尾。
    ^
    ([^?#]+)
    (?:
    \?
    ([^#]+)
    )?
    (?:
    #
    (.*)
    )?
    $

    让我们 do some clean up在深入研究查询字符串之前。通过替换第一个捕获组,您可以轻松地要求路径等于某个值。无论您用什么( path )替换它,都必须后跟一个可选的查询字符串、一个可选的 anchor 和字符串的结尾(不多也不少)。由于您不需要解析 anchor ,因此可以通过在 # 处结束匹配来替换捕获组。或字符串的结尾(即查询参数的结尾)。
    ^path
    (?:
    \?
    ([^#\+)
    )?
    (?=#|$)

    停止瞎闹

    好的,我已经做了很多设置,而没有真正担心你的具体例子。下一个示例将匹配特定路径 ( path ) 并可选择匹配查询字符串,同时捕获 foo 的值范围。这意味着您可以在此处停止并检查有效匹配。如果匹配有效,则第一个捕获组必须是 null或非负整数。但这不是你的问题,是吗。 This got a lot more complicated ,所以我将解释内联表达式:
    ^            (?# match beginning of the string)
    path (?# match path literally)
    (?: (?# begin optional non-capturing group)
    (?=\?) (?# lookahead for a literal ?)
    (?: (?# begin optional non-capturing group)
    [?&] (?# keys are preceded by ? or &)
    foo (?# match key literally)
    (?: (?# begin optional non-capturing group)
    = (?# values are preceded by =)
    ([^&#]*) (?# values are 0+ length and do not contain & or #)
    ) (?# end optional non-capturing group)
    | (?# OR)
    [^#] (?# query strings are non-# characters)
    )+ (?# end repeating non-capturing group)
    )? (?# end optional non-capturing group)
    (?=#|$) (?# lookahead for a literal # or end of the string)

    这里的一些关键要点:
  • Javascript 不支持lookbehinds,这意味着你不能向后看?&前键foo ,这意味着您实际上必须匹配这些字符之一,这意味着您的查询字符串(查找 ? )的开头必须是前瞻,以便您实际上不匹配 ? .这也意味着您的查询字符串将始终至少是一个字符( ? ),因此您要重复查询字符串 [^#] 1+次。
  • 查询字符串现在在非捕获组中一次重复一个字符..除非它看到键 foo ,在这种情况下,它捕获可选值并继续重复。
  • 由于此非捕获查询字符串组一直重复到 URI 的 anchor 或结尾,因此第二个 foo 值 ( path?foo=123&foo=bar ) 将覆盖初始捕获值..意味着您不能 100% 依赖上述解决方案。


  • 最终解决方案?

    好的..现在我已经捕获了 foo值(value),它是 time to kill the match on a values that are not positive integers .
    ^            (?# match beginning of the string)
    path (?# match path literally)
    (?: (?# begin optional non-capturing group)
    (?=\?) (?# lookahead for a literal ?)
    (?: (?# begin optional non-capturing group)
    [?&] (?# keys are preceeded by ? or &)
    foo (?# match key literally)
    = (?# values are preceeded by =)
    (\d*) (?# value must be a non-negative integer)
    (?= (?# begin lookahead)
    [&#] (?# literally match & or #)
    | (?# OR)
    $ (?# match end of the string)
    ) (?# end lookahead)
    | (?# OR)
    (?! (?# begin negative lookahead)
    [?&] (?# literally match ? or &)
    foo= (?# literally match foo=)
    ) (?# end negative lookahead)
    [^#] (?# query strings are non-# characters)
    )+ (?# end repeating non-capturing group)
    )? (?# end optional non-capturing group)
    (?=#|$) (?# lookahead for a literal # or end of the string)

    让我们仔细看看 juju 的一些进入那个表达:
  • 找到后foo=\d* ,我们使用前瞻来确保它后面跟着一个 & , # ,或字符串的结尾(查询字符串值的结尾)。
  • 但是..如果还有更多到foo=\d* ,正则表达式将被交流发电机踢回通用 [^#]匹配在 [?&]之前 foo .这不好,因为它会继续匹配!因此,在查找通用查询字符串 ( [^#] ) 之前,您必须确保查看的不是 foo (必须由第一次交替处理)。这是负前瞻(?![?&]foo=)的地方派上用场了。
  • 这将适用于多个 foo键,因为它们都必须等于非负整数。这让 foo也是可选的(或等于 null )。


  • 免责声明:大多数 Regex101 演示使用 PHP 来实现更好的语法突出显示并包括 \n在否定字符类中,因为有多行示例。

    关于javascript - 如何在 Javascript 中使用正则表达式提取可选查询参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25846961/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com