【问题标题】:RegEx for matching a word after specific word in multiple lines用于在多行中匹配特定单词之后的单词的正则表达式
【发布时间】:2019-09-25 17:49:13
【问题描述】:

在某些编辑器(如 VS Code)中,有正则表达式功能来查找单词而不是“Ctrl + F”,我试图在特定单词之后找到另一个单词。

例如,如何使用正则表达式过滤具有特定“消息”属性的“someFunction”,如下所示:

...
someFunction({
  a: true,
  b: false
})
someFunction({
  a: true,
  b: false,
  c: false,
  d: true,
  message: 'I wnat to find the funciton with this property'
})
someFunction({
  a: true
})
...

我试过的正则表达式是这样的:

/someFunction[.*\s*]*message/

但是没有用

我怎样才能实现这个目标?

【问题讨论】:

  • 你使用的是什么版本的 VS Code?根据this answer,在 v1.29(2018 年 11 月发布)中添加了多行搜索。
  • 您的参考链接是正确的!我需要使用“\n”来启用多行搜索。我使用的最后一个正则表达式是 /someFunction[\S\n\s*]*message/

标签: javascript regex visual-studio-code regex-group regex-greedy


【解决方案1】:

你的表达很好,你可能想稍微修改一下:

 someFunction[\S\s*]*message

如果你也想得到这个属性,这个表达式可能会起作用:

(someFunction[\S\s*]*message)(.*)

您可以根据需要添加其他边界,可以使用regex101.com。

图表

此图显示了您的表达式将如何工作,您可以在jex.im 中可视化其他表达式:

性能测试

此脚本针对表达式返回字符串的运行时间。

repeat = 1000000;
start = Date.now();

for (var i = repeat; i >= 0; i--) {
	var string = "some other text someFunction \n            \n message: 'I wnat to find the funciton with this property'";
	var regex = /(.*)(someFunction[\S\s*]*message)(.*)/g;
	var match = string.replace(regex, "$3");
}

end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match ??? ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. ? ");

const regex = /(someFunction[\S\s*]*message)(.*)/;
const str = `...
someFunction({
  a: true,
  b: false
})
someFunction({
  a: true,
  b: false,
  c: false,
  d: true,
  message: 'I wnat to find the funciton with this property'
})
someFunction({
  a: true
})
...`;
let m;

if ((m = regex.exec(str)) !== null) {
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
        console.log(`Found match, group ${groupIndex}: ${match}`);
    });
}

【讨论】:

  • 哇,你的回答太棒了!这些工具对我来说真的很有用!
【解决方案2】:

在您的模式someFunction[.*\s*]*message 中,您可以使用character class,它将只匹配几个字符中的一个并且可以写为[.*\s]

使用[\S\s]* 之类的模式不会考虑任何其他具有相同名称或闭合边界(例如}))的函数,并且会过度匹配它。

如果未启用 pcre2,this page 会说明如何启用它,您可以使用前瞻。

如果你想要更精确的匹配,你可以使用:

^someFunction\(\{(?:\n(?!(?: +message:|}\))).*)*\n +message:(.*)\n}\)$

说明

  • ^ 字符串开始
  • someFunction\(\{匹配someFunction({
  • (?:非捕获组
    • \n匹配换行符
    • (?! 负前瞻
      • (?:非捕获组
        • +message: 匹配 1+ 个空格后跟消息:
        • |或者
        • }\)匹配})
      • )关闭非捕获组
    • ) 关闭负前瞻
    • .* 匹配除换行符以外的任何字符
  • )*关闭无捕获组,重复0+次
  • \n +message:匹配换行符和消息:
  • (.*)\n 在第 1 组中捕获匹配除换行符后跟换行符之外的任何字符
  • }\)匹配})
  • $字符串结束

Regex demo

【讨论】:

  • 太棒了!这对于分离过滤结果非常有用。虽然有点复杂,但是你还是解释的很清楚,我会花一点时间学习一下,谢谢!
【解决方案3】:

您可以在 VScode 中使用正则表达式进行多行搜索。

如果您在文件中有多个 someFunction 并且您只想找到具有 message 字段的那些,但跳过那些没有 message 字段的那些。

使用下面的

  • 使用惰性限定符+?,它匹配从第一次出现someFunction到第一次出现message的文本块
  • 使用[^)] 确保someFunction 和message 之间没有右括号
  • 使用\n匹配多行
someFunction([^)]|\n)+?message:

【讨论】:

    【解决方案4】:

    VSCode uses RipGrep 使用Rust regex。

    以下模式将匹配“消息”

    要选择直到行尾,

    (?<=someFunction.*(\n.+)+)message.*$
    

    要仅选择键,请省略 .*$

    (?<=someFunction.*(\n.+)+)message
    

    【讨论】:

    • 链接的第二句话说,“但缺少环顾和反向引用等一些功能”,因此您建议的环顾使用无效。为了在 VS Code 的搜索功能中使用环视,您需要启用 PCRE2 而不是使用默认值(Rust 的正则表达式引擎)。
    猜你喜欢
    • 1970-01-01
    • 2022-06-11
    • 2021-09-21
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    相关资源
    最近更新 更多