To “match anything” is one of the most common use cases for regex, or at least to have strings or match groups A and B and then match anything in between them. The methods to do so can basically be divided in two: Matching every thing on the same line or matching anything even with linebreaks. So that’s what were gonna have a look at now.
Match on one line
const testString = `
Hello World!
I will always be here for you.
Yours Sincerely
`
const regex = /I will(.*?)for you./
console.log(regex.exec(testString));
Result:
[
'I will always be here for you.',
' always be here ',
index: 14,
input: '\nHello World!\nI will always be here for you.\nYours Sincerely\n',
groups: undefined
]
Match over multiple lines
This is where it becomes a little more tricky, but only a little.
In modern JS versions: Use dotall
You can now pass your regex the “dotall” flag, which means . also matches newlines. The flag to do so is s.
const testString = `
A
B
C
D
`
const regex = /A(.*?)D/s
console.log(regex.exec(testString));
// Output:
// [
// 'A\nB\nC\nD',
// '\nB\nC\n',
// index: 1,
// input: '\nA\nB\nC\nD\n',
// groups: undefined
// ]
So what does modern JS versions mean here? Theoretically it means ES2018, 9th edition of JavaScript, but in reality you should be more concerned with whether your runtime supports it:
NodeJS: >= 10.3
Chrome: >= 62
Edge: >= 79
Firefox: >= 78
IE: nah
Opera: 49
Safari: 12
By now all modern browsers and all supported NodeJS versions have it, so unless you have to support ancient runtimes you can just use it.
For older JavaScript versions (pre ES2018, 9th edition)
const testString = `
import {
A,
B,
C
}
import {
E,
F
}
`
const regex = /import ([\s\S]*?})/g
console.log(regex.exec(testString));
Or if you prefer to work with new RegExp, but take care of the escaping:
const testString = `
import {
A,
B,
C
}
import {
E,
F
}
`
const regex = new RegExp('import ([\\s\\S]*?})', 'g')
console.log(regex.exec(testString));
Result:
[
'import {\n A,\n B,\n C\n}',
'{\n A,\n B,\n C\n}',
index: 1,
input: '\nimport {\n A,\n B,\n C\n}\nimport {\n E,\n F\n}\n',
groups: undefined
]
Pitfalls
- Dotall only exists since ES2018
- Do NOT use the multiline flag when matching on multiple lines. It is the opposite of what you want since it cuts the string into its individual lines.
- Beware of escaping, as the examples show. Since it’s simpler with the
/.../syntax I’d suggest to always go for this when using regex, since regex is illegible enough as it is. - Think about whether regex is the right tool, do not write html parsers with it ;)
Conclusion
Regex + Match Anything is a powerful tool. The basic syntax is . for single-line or with the s flag for multi-line matching, or [\s\S] for multi-line matching on older JS versions.
I find myself mostly using the non-greedy versions with match groups: (.*?). I can sometimes even manage to type it out correctly on the first try. 😉