如何使用多个捕获组进行正则表达式替换?

How do I do regex substitutions with multiple capture groups?

我正在尝试允许用户使用唯一控制字符为 * 的 glob 模式来过滤文本字符串。在幕后,我认为过滤列表字符串最简单的方法是使用 Js.Re.test[https://rescript-lang.org/docs/manual/latest/api/js/re#test_],这很简单。

暂时忽略用户过滤器字符串上的 *,我遇到的困难是转义所有 RegEx 控制字符。具体来说,我不知道如何替换输入文本中的捕获组以创建新字符串。

到目前为止,我已经知道了,但不太正确:

let input = "test^ing?123[foo";

let escapeRegExCtrl = searchStr => {
    let re = [%re("/([\^\[\]\.\|\\\?\{\}\+][^\^\[\]\.\|\\\?\{\}\+]*)/g")];

    let break = ref(false);
    while (!break.contents)  {
        switch (Js.Re.exec_ (re, searchStr)) {
            | Some(result) => {
                let match = Js.Re.captures(result)[0];
                Js.log2("Matching: ", match)
            }
            | None => {
                break := true;
            }
        }
    }
};
search -> escapeRegExCtrl

如果我忽略被跳过的字符串的“测试”部分,上面的输出将产生:

Matching: ^ing  
Matching: ?123 
Matching: [foo

对于上面的例子,在一天结束时,我想要产生的是这个(有前导和跟随 .*:

.*test\^ing\?123\[foo.*

但我不确定如何从匹配的捕获组中创建 连续 字符串。

echo "test^ing?123[foo" | sed -r 's_([\^\?\[])_\_g' 将在命令行上完成工作)


编辑

根据 Chris Maurer 的回答,JS 库中有一个方法可以满足我的需求。稍加挖掘就暴露了该方法的 ReasonML 代理: https://rescript-lang.org/docs/manual/latest/api/js/string#replacebyre

让我看看我是否有这个权利;你想实现一个字符匹配器,其中除了 *.据推测 * 应该像 Windows dir 命令中那样工作,匹配零个或多个字符。

此外,您想通过将用户输入的字符串直接传递给 Regexp 匹配函数,然后对其进行适当的清理以仅处理 *.

来实现它

如果我没看错,那么听起来您需要做两件事才能为 js.re.test:

准备好字符串
  1. 引用所有特殊的正则表达式字符,并且
  2. 将所有 * 实例变成 .* 或 .*?

让我们保持简单,分两步处理字符串,每一步都使用 Js.re.replace。所以正则表达式中的特殊字符列表是 [^$.|?*+()。适当地引用这些替换:

str.replace(/[\[\\^$\.\|\?\+\(\)]/g, '$&')

这就是引用的所有特殊字符。替换规范中的 $& 表示插入任何匹配的内容。 然后将该结果传递给第二个将 * 替换为 .*?转型.

str.replace(/*+/g, '.*?')