4

There is regex feature to find words instead of "Ctrl + F" in some editor like VS Code, I'm trying to find a word after a specific word with some another lines.

For example, how to use regex to filter those "someFunction" with the specific "message" property as below:

...
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
})
...

The regex I tried is like:

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

But it did't work

How can I achieve this aim?

Emma
  • 27,428
  • 11
  • 44
  • 69
Chris Kao
  • 410
  • 4
  • 12
  • What version of VS Code are you using? Multiline search was added in v1.29 (released November 2018), as per [this answer](https://stackoverflow.com/a/53270908). – Hoppeduppeanut May 08 '19 at 03:44
  • Your reference link is correct! I need to use "\n" to enable the multiline search. The final regex I used is /someFunction[\S\n\s*]*message/ – Chris Kao May 08 '19 at 06:57

4 Answers4

12

Your expression is just fine, you might want to slightly modify it as:

 someFunction[\S\s*]*message

If you wish to also get the property, this expression might work:

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

You can add additional boundaries, if you like, maybe using regex101.com.

enter image description here

Graph

This graph shows how your expression would work and you can visualize other expressions in jex.im:

enter image description here

Performance Test

This script returns the runtime of a string against the expression.

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}`);
    });
}
Emma
  • 27,428
  • 11
  • 44
  • 69
2

you could use regex for mutliple-line search in VScode.

If you have several someFunction in the file and you only want to find the ones that have message field but skip those the others without message field in it.

use the following

  • Use lazy qualifier +?, it matches the text block from the first occurrence someFunction to the first occurrence of message
  • Use [^)] to make sure there is no close bracket between the someFunction and message
  • use \n to match multiple lines
someFunction([^)]|\n)+?message:

enter image description here

enter image description here

Hui Zheng
  • 2,394
  • 1
  • 14
  • 18
1

In your pattern someFunction[.*\s*]*message, you can make use of a character class, which will match only one out of several characters and can be written as [.*\s]

Using a pattern like [\S\s]* will not take any other functions with the same name or closing boundaries like }) into account and will over match it.

If pcre2 is not enabled, this page explains how to enable it you make use of the lookahead.

If you want a more precise match, you could use:

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

Explanation

  • ^ Start of string
  • someFunction\(\{ Match someFunction({
  • (?: Non capturing group
    • \n Match newline
    • (?! Negative lookahead
      • (?: Non capturing group
        • +message: Match 1+ spaces followed by message:
        • | Or
        • }\) Match })
      • ) Close non capturing group
    • ) Close negative lookahead
    • .* Match any char except a newline
  • )* Close no capturing group and repeat 0+ times
  • \n +message: Match newline and message:
  • (.*)\n Capture in group 1 matching any char except a newline followed by a newline
  • }\) Match })
  • $ End of string

Regex demo

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • 2
    Amazing! That's really useful for separate the filter result. Although it is a little bit complicated, you still explained it in a very clear way, I will take a little time to learn it, thanks! – Chris Kao May 13 '19 at 05:48
-1

VSCode uses RipGrep which uses Rust regex.

The following pattern will match 'message'

To select till the end of the line,

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

to select only the key, omit .*$

(?<=someFunction.*(\n.+)+)message
sorja
  • 52
  • 2
  • 1
    The second sentence of your link says, "but lacks a few features like look around and backreferences," so your suggested use of look-around won't work. In order to use look-around in VS Code's search functionality, you need to enable PCRE2 instead of using the default (Rust's regex engine). – BurntSushi5 May 08 '19 at 12:44