如何从 javascript 中的某个位置匹配正则表达式模式?

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

我正在尝试在 javascript 中使用正则表达式匹配降价 header。降价 header 是一个字符串,从一个或多个 # 开始,后跟一个或多个空格和一些文本,如下所示:

## This is the title

棘手的是,我得到了一个 multi-line 字符串和一个 0 索引的起始位置,我需要检查从给定位置开始的字符串是否 starts 降价 header。换句话说,我需要编写以下函数:

/**
 * 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) {
    ...
}

这是我试过的方法:

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.

该函数应该在第二次调用时 return false。但它没有。为什么?我怎样才能让它发挥作用?

您不需要正则表达式从特定位置开始。您可以只传递从 startPos:

开始的子字符串
return pattern.exec(text.substring(startPos)) != null;

使用正则表达式的解决方案

你可以使用

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

函数看起来

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

注意:这里我使用了 s 标志。另外,请参阅 demo.

使用 Slice 的解决方案

您可以在检查有效性之前对输入字符串进行切片。

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

编辑

isMarkdownHeader("abcd## My Title\nxyz", 4) should return false. With your code, the return value is true

发生这种情况是因为称为换行符的东西和 \n 字符不是一回事。字符串中的\n是换行符的常规字符,打印字符串后就变成了换行符。所以如果你想匹配他们两个然后使用

^.{4}(?:^|\n|\n)(#+\s+.*)

这里我在旧的基础上添加了(?:^|\n|\n)模式

  • (?:Non-capturing组
    • ^|\n|\n 匹配 字符串开头 换行符 \n 字符
  • )关闭non-capturing群

它匹配

它不匹配

P.S。要匹配 abc\n## My Title\nxyz,您必须使用 3 作为 startPos,不包括 \n 字符。

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

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

根据 Regex101{0} 量词导致前面的标记被忽略。没有引文支持这一点,但我会相信他们的话。

既然如此,您可以检查您的匹配项是否从索引 0 开始(这表明字符串以正确数量的忽略字符开始)。

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