Home > OS >  How to match a regex pattern from a certain position in javascript?
How to match a regex pattern from a certain position in javascript?

Time:06-04

I'm trying to match the markdown header using regex in javascript. A markdown header is a string starting from one or more # followed by one or more spaces and some more texts, like this:

## This is the title

The tricky thing is, I'm given a multi-line string and a 0-indexed start position, I need to check if the string starting from the given position starts with a markdown header. In other words, I need to write the following function:

/**
 * The function should return true in the following situations:
 * - text: "abc\n# My Title", startPos = 4
 * - text: "abc\n# My Title\nxyz", startPos = 4
 * 
 * The function should return false in the following situation:
 * - text "abc\n#My Title", startPos = 0
 */
function isMarkdownHeader(text, startPos) {
    ...
}

Here is what I've tried:

function isMarkdownHeader(text, startPos) {
    const pattern = new RegExp(`^[^]{${startPos}}(^# )(\\s )(.*$)`, 'm');
    return pattern.exec(text) != null;
}

console.log(isMarkdownHeader("abc\n## My Title\nxyz", 4)); // true
console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)); // true, which is incorrect.

The function should return false in the second invocation. But it didn't. Why? How can I make it work?

CodePudding user response:

Solution using Regex

You can use

^.{4}(# \s .*)

And the function will look

function isMarkdownHeader(text, startPos) {
    const pattern = new RegExp(`^.{${startPos}}# \\s .*`, "s");
    return pattern.exec(text) != null;
}

isMarkdownHeader("abc\n## My Title\nxyz", 4)  // true
isMarkdownHeader("abc\n## My Title\nxyz", 0)  // false

NOTE: Here I have used s flag. Also, see the demo.

Solution using slice

You can slice the input string before checking the validity.

function isMarkdownHeader(text, startPos) {
    const pattern = /^# \s .*/;
    return !!pattern.exec(text.slice(startPos));
}

isMarkdownHeader("abc\n## My Title\nxyz", 4)  // true
isMarkdownHeader("abc\n## My Title\nxyz", 0)  // false

CodePudding user response:

According to Regex101, the {0} quantifier causes the previous token to be ignored. There's no citation to back that, but I'll take them at their word.

That being so, you can check that your match starts at index 0 (which indicates that the string started with the correct number of ignored characters).

function isMarkdownHeader(text, startPos) {
    const pattern = new RegExp(`^[^]{${startPos}}(^# )(\\s )(.*$)`, 'm');
    const match = pattern.exec(text);
    return match?.index === 0;
}

console.log(isMarkdownHeader("abc\n## My Title\nxyz", 4)); // true
console.log(isMarkdownHeader("abc\n## My Title\nxyz", 0)); // now false

CodePudding user response:

You don't need the regex to start at a certain position. You can just pass the substring starting at startPos:

return pattern.exec(text.substring(startPos)) != null;
  • Related