如何仅在查询参数存在时使用字符串替换所有正则表达式来替换查询参数

How to replace query parameter only if it exists using string replace All regex

我有以下网址:

https://test1.com/path?query1=value1

and

https://test2.com/path

我正在尝试向所有网址添加额外的查询参数,所以我正在尝试类似

的方法
url.replaceAll(/(.*)[?]?(.*)/g,"?newquery=newvalue&")

let url = "https://test1.com/path?query1=value1"
console.log(url.replaceAll(/^(.*)[?]?(.*)$/g,"?newquery=newvalue&"))
url = "https://test1.com/path"
console.log(url.replaceAll(/^(.*)[?]?(.*)$/g,"?newquery=newvalue&"))

但它没有按预期工作,有人可以解释一下吗

首先让我们检查一下您的正则表达式在做什么,然后我们可以修复它。 您的正则表达式:

^ - the beginning of the string
(.*) - match any character 0 or more times - as many times as possible (greedy)
[?]? - match `?` 0 or 1 times
(.*) - match any character 0 or more times - as many times as possible (greedy)
$ - the end of the string

这里真正的主要问题是第一个捕获组捕获了尽可能多的次数,所以它总是匹配整个 url。我们可以通过使用 .*? 来得到 non-greedy,所以我们最终得到 ^(.*?)[?]?(.*)$。但是现在我们遇到了 last 捕获组捕获整个 url 的问题 - 我们可以使这个 non-greedy 但它不会匹配任何字符根本。相反,我们应该确保该组仅在出现 ? 时捕获,因此我们可以设置 [?]? non-optional,将其移至下一个捕获组,并将最后一个组设为可选,像这样:([?](.*))?。在我们这样做的同时,我们也可以使用 \? 而不是 [?],我们最终会得到 ^(.*?)(\?(.*))?$。这是可行的,因为 $ 表示我们要一直捕获到最后。有了这个,我们需要使用 </code> 而不是 <code>,因为 </code> 现在在替换时也包含 <code>?,所以我们可以使用 non-capturing 组来消除那个问题。 所以我们最终的正则表达式是 /(.*?)(?:\?(.*))?/g.

您的最终代码将如下所示:

let url = "https://test1.com/path?query1=value1"
console.log(url.replaceAll(/^(.*?)(?:\?(.*))?$/g,"?newquery=newvalue&"))
url = "https://test1.com/path"
console.log(url.replaceAll(/^(.*?)(?:\?(.*))?$/g,"?newquery=newvalue&"))