如何使用多个捕获组进行正则表达式替换?
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:
准备好字符串
- 引用所有特殊的正则表达式字符,并且
- 将所有 * 实例变成 .* 或 .*?
让我们保持简单,分两步处理字符串,每一步都使用 Js.re.replace。所以正则表达式中的特殊字符列表是 [^$.|?*+()。适当地引用这些替换:
str.replace(/[\[\\^$\.\|\?\+\(\)]/g, '$&')
这就是引用的所有特殊字符。替换规范中的 $& 表示插入任何匹配的内容。
然后将该结果传递给第二个将 * 替换为 .*?转型.
str.replace(/*+/g, '.*?')
我正在尝试允许用户使用唯一控制字符为 *
的 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:
准备好字符串- 引用所有特殊的正则表达式字符,并且
- 将所有 * 实例变成 .* 或 .*?
让我们保持简单,分两步处理字符串,每一步都使用 Js.re.replace。所以正则表达式中的特殊字符列表是 [^$.|?*+()。适当地引用这些替换:
str.replace(/[\[\\^$\.\|\?\+\(\)]/g, '$&')
这就是引用的所有特殊字符。替换规范中的 $& 表示插入任何匹配的内容。 然后将该结果传递给第二个将 * 替换为 .*?转型.
str.replace(/*+/g, '.*?')