javascript - 如何使用 Javascript 正则表达式检测没有评论和 Markdown 的句子?

标签 javascript regex comments markdown

问题

我有一段文字。它可以包含从 ASCII 32(空格)到 ASCII 126(波浪号)的所有字符,包括 ASCII 9(水平制表符)。

文本可能包含句子。每个句子以点、问号或感叹号结尾,紧跟空格。

文本可能包含基本的 Markdown 样式,即:粗体文本( ** ,也称为 __ ),斜体文本( * ,也称为 _ )和删除线( ~~ )。 Markdown 可能出现在句子内部(例如 **this** is a sentence. )或句子外部(例如 **this is a sentence!** )。 Markdown可能不会出现跨句,也就是可能不会这样的情况:**sentence. sente** nce. . Markdown 可能包含不止一句话,即可能这样的情况:**sentence. sentence.** .

它还可以包含两个字符序列:<!----> .这些序列之间的所有内容都被视为注释(就像在 HTML 中一样)。注释可以出现在文本的任何位置,但不能包含换行符(我希望在 Linux 上它只是 ASCII 10)。

我想检测 Javascript 中的所有句子,并为每个句子在评论中将其长度放在该句子之后,如下所示:sentence.<!-- 9 --> . 主要是,我不关心它们的长度是否包括 Markdown 标签的长度,但如果不包括就好了。

到目前为止我做了什么?

到目前为止,在这个 answer 的帮助下,我准备了以下用于检测句子的正则表达式。它最符合我的需要——除了它包含评论。

const basicSentence = /(?:^|\n| )(?:[^.!?]|[.!?][^ *_~\n])+[.!?]/gi;

我还准备了以下用于检测评论的正则表达式。它也按预期工作,至少在我自己的测试中是这样。

const comment = /<!--.*?-->/gi;

例子

为了更好地了解我想要实现的目标,让我们举个例子。比如说,我有以下一段文字:

foo0 
b<!-- comment -->ar.
foo1 bar?
<!-- comment -->

foo2bar!

(最后还有一个换行符,但我不知道如何在 Stackoverflow markdown 中添加一个空行。)

预期的结果是:

foo0 
b<!-- comment -->ar.<!-- 10 -->
foo1 bar?<!-- 9 -->
<!-- comment -->

foo2bar!<!-- 12 -->

(这一次,末尾也没有没有换行符。)


更新:抱歉,我已经更正了示例中的预期结果。

最佳答案

将回调传递给 .replace用空字符串替换所有注释,然后返回结果 trim 匹配的长度:

const input = `foo0 
b<!-- comment -->ar.
foo1 bar?
<!-- comment -->

foo2bar!
`;
const output = input.replace(
  /(?:^|\n| )(?:[^.!?]|[.!?][^ *_~\n])+[.!?]/g,
  (match) => {
    const matchWithoutComments = match.replace(/<!--.*?-->/g, '');
    return `${match}<!-- ${matchWithoutComments.length} -->`;
  }
);
console.log(output);

当然,如果您愿意,您也可以使用类似的模式将 markdown 符号替换为内部文本内容:

.replace(/([*_]{1,2}|~~)((.|\n)*?)\1/g, '$2')

(由于嵌套和可能不平衡的标签,正则表达式不太适合使用,您可能必须重复该行,直到找不到进一步的替换)

此外,根据评论,您当前的正则表达式期望每个句子都以 . 结尾, ! , 或 ? .评论的!<!--被视为(短)句的结尾。一种选择是在正则表达式的最后查找空格(空格或换行符)或输入的结尾:

const input = `foo0 
b<!-- comment -->ar.
foo1 bar?
<!-- comment -->

foo2bar!
<!-- comment -->`;
const output = input.replace(
  /(?:^|\n| )(?:[^.!?]|[.!?][^ *_~\n])+[.!?](?=\s|$|[*_~])/g,
  (match) => {
    const matchWithoutComments = match.replace(/<!--.*?-->/g, '');
    return `${match}<!-- ${matchWithoutComments.length} -->`;
  }
);
console.log(output);

https://regex101.com/r/RaTIOi/1

关于javascript - 如何使用 Javascript 正则表达式检测没有评论和 Markdown 的句子?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53017709/

相关文章:

c - 在 C 中,fgets 和 continue 跳过不止一行

javascript - JS中如何读取特殊字符后的值

javascript - 在javascript中引用正则表达式文字?为什么不?

javascript - .map 使用 Mongoose 获取数据后返回空对象数组

regex - 是否有更优雅的正则表达式解决方案可用于匹配短字符串中的多个模式

c# - 删除 HTML 注释

javascript - Rails 使用 JSON 对象渲染部分

python - 带有数字和大写字母的字符串的正则表达式匹配失败

regex - 前瞻和后向正则表达式

comments - 代码注释中的#XXX是什么意思?