在javascript中将字符串拆分为句子

IT技术 javascript regex
2021-03-17 17:12:28

目前我正在开发一个将长列拆分为短列的应用程序。为此,我将整个文本拆分为单词,但目前我的正则表达式也将数字拆分。

我做的是这样的:

str = "This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence.";
sentences = str.replace(/\.+/g,'.|').replace(/\?/g,'?|').replace(/\!/g,'!|').split("|");

结果是:

Array [
    "This is a long string with some numbers [125.",
    "000,55 and 140.",
    "000] and an end.",
    " This is another sentence."
]

想要的结果是:

Array [
    "This is a long string with some numbers [125.000, 140.000] and an end.",
    "This is another sentence"
]

我必须如何更改我的正则表达式才能实现这一目标?我是否需要注意可能会遇到的一些问题?或者搜索". ","? "和 就足够了"! "

6个回答
str.replace(/([.?!])\s*(?=[A-Z])/g, "$1|").split("|")

输出:

[ 'This is a long string with some numbers [125.000,55 and 140.000] and an end.',
  'This is another sentence.' ]

分解:

([.?!])= 捕获.?!

\s*= 在前一个标记之后捕获 0 个或多个空白字符([.?!])这说明了与英语语法匹配的标点符号后面的空格。

(?=[A-Z])= 仅当下一个字符在范围 AZ(大写 A 到大写 Z)内时,前一个标记才匹配。大多数英语句子以大写字母开头。以前的正则表达式都没有考虑到这一点。


替换操作使用:

"$1|"

我们使用了一个“捕获组”([.?!])并捕获了其中一个字符,并将其替换为$1(匹配项) plus |因此,如果我们捕获了,?那么替换将是?|.

最后,我们拆分管道|并得到我们的结果。


所以,本质上,我们要说的是:

1)找到标点符号(.?或之一!)并捕获它们

2) 标点符号之后可以有选择地包含空格。

3)在标点符号之后,我希望有一个大写字母。

与之前提供的正则表达式不同,这将正确匹配英语语言语法。

从那里:

4)我们通过附加一个管道来替换捕获的标点符号 |

5)我们拆分管道以创建一个句子数组。

如果句子以数字开头,则此解决方案失败。
2021-04-18 17:12:28
我看不出忽略条件 A 如何导致歧义语法。点歧义可以通过几个规则解决(不完美,但仍然是一个非常实用的解决方案):1)两位数之间的点是小数点分隔符;2)除两位数字外的任何东西之间的点是标点符号 - 句子分隔符。
2021-04-25 17:12:28
“我女儿 10 岁。再过 10 年,她将 20 岁。” ?
2021-05-05 17:12:28
有关计算机科学中语法歧义的更多信息:en.wikipedia.org/wiki/Ambiguous_grammar本质上,在您的情况下,带有小数分隔符的数字和新句子的标点符号需要在语法上可区分。我提供的修改后的正则表达式符合英语语法。
2021-05-10 17:12:28
您可以将其修改为:/([.?!])\x20{1,2}(?=[AZ\d])/。但是,这会期望 A) 十进制数字后面没有空格,并且 B) 标点符号后面有一个或两个空格字符。这将符合英语语法。如果您不能接受条件 A,那么您尝试解析的语法就会有歧义。
2021-05-11 17:12:28
str.replace(/(\.+|\:|\!|\?)(\"*|\'*|\)*|}*|]*)(\s|\n|\r|\r\n)/gm, "$1$2|").split("|")

RegExp(参见Debuggex):

  • (.+|:|!|\?) = 句子不仅可以以“.”、“!”结尾 或“?”,但也可以通过“...”或“:”
  • (\" |\' |)*|} |] ) = 句子可以用引号或括号括起来
  • (\s|\n|\r|\r\n) = 句子后必须是空格或行尾
  • g = 全局
  • m = 多行

评论:

  • 如果使用 (?=[AZ]),则 RegExp 在某些语言中将无法正常工作。例如,“Ü”、“Č”或“Á”将不会被识别。

您可以利用下一个句子以大写字母或数字开头。

.*?(?:\.|!|\?)(?:(?= [A-Z0-9])|$)

正则表达式可视化

调试器演示

它拆分此文本

This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence. Sencenes beginning with numbers work. 10 people like that.

成句子:

This is a long string with some numbers [125.000,55 and 140.000] and an end.
This is another sentence.
Sencenes beginning with numbers work.
10 people like that.

提琴手

这很棒,我只是注意到它不能处理糟糕的用户输入,例如“Jim 去了商店。Larry 一直睡到 12 点。但是 Becky 周末离开了。” 但是,这超出了问题的范围。我只是为像我这样可能正在寻找快速正则表达式来处理这个问题的人提到它。
2021-04-19 17:12:28
这也搞不定?或者 !
2021-05-06 17:12:28

如果后面没有空格 + 字符字符,请使用前瞻来避免替换点:

sentences = str.replace(/(?=\s*\w)\./g,'.|').replace(/\?/g,'?|').replace(/\!/g,'!|').split("|");

输出:

["This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence."]

使用前瞻来确保点之后的内容不是数字会更安全。

var str ="This is a long string with some numbers [125.000,55 and 140.000] and an end. This is another sentence."

var sentences = str.replace(/\.(?!\d)/g,'.|');
console.log(sentences);

如果你想更安全,你可以检查后面是否也是数字,但由于 JS 不支持后视,你需要捕获前一个字符并在替换字符串中使用它。

var str ="This is another sentence.1 is a good number"

var sentences = str.replace(/\.(?!\d)|([^\d])\.(?=\d)/g,'$1.|');
console.log(sentences);

一个更简单的解决方案是对数字中的点进行转义(例如用 $$$$ 替换它们),进行拆分,然后对点进行转义。

这是唯一一个对我来说完美的。(第一个版本)
2021-05-02 17:12:28