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

问题描述 投票:2回答:1

Problem

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

文字可能包含句子。每个句子都以点,问号或感叹号结尾,后面跟着空格。

文本可能包含基本的降价样式,即:粗体文本(**__),斜体文本(*_)和删除线(~~)。降价可能发生在句子(例如**this** is a sentence.)或其外部(例如**this is a sentence!**)。 Markdown可能不会在句子中出现,也就是说,可能不会出现这样的情况:**sentence. sente** nce.。 Markdown可能包含多个句子,也就是说,可能存在这样的情况:**sentence. sentence.**

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

我想在Javascript中检测所有句子,并且每个句子都将它的长度放在评论之后,如下所示:sentence.<!-- 9 -->。主要是,我不在乎它们的长度是否包括降价标签的长度,但如果它没有,那将是很好的。

What have I done so far?

到目前为止,在这个answer的帮助下,我准备了以下正则表达式来检测句子。它主要满足我的需求 - 除了它包括评论。

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

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

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

Example

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

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

foo2bar!

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

预期的结果是:

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

foo2bar!<!-- 12 -->

(这次,有 没有 也是最后的换行符。)


更新:对不起,我已经更正了示例中的预期结果。

javascript regex comments markdown
1个回答
3
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.