正则表达式匹配标点符号和空格,但保留标点符号。

4
使用JavaScript的 .split() 方法来将一个包含大段文字的字符串分成句子。需要使用正则表达式匹配以句号或问号开头,并带有一个空格符号[?.],同时需要在结果数组中保留句号/问号。如何在JS中实现这一点而不使用正向回溯呢?
编辑:输入示例:"This is sentence 1. This is sentence 2? This is sentence 3.",输出示例:["This is sentence 1.", "This is sentence 2?", "This is sentence 3."]

你想要分割还是匹配?如果你想要匹配,可以**轻松地**完成。 - rock321987
请提供清晰的“输入”和期望的“输出”样例。 - Pedro Lobito
编辑以添加示例,以澄清。 - jswny
5个回答

1
忘掉split()。你想要match()
var text = "This is an example paragragh. Oh and it has a question? Ok it's followed by some other random stuff. Bye.";

var matches = text.match(/[\w\s'\";\(\)\,]+(\.|\?)(\s|$)/g);


alert(matches);

生成的匹配数组包含每个句子:
    Array[4]
        0:"This is an example paragragh. "
        1:"Oh and it has a question? "
        2:"Ok it's followed by some other random stuff. "
        4:"Bye. "

以下是相关的 jsfiddle 用于进一步测试: https://jsfiddle.net/uds4cww3/

已编辑以匹配行末。


我的段落中有逗号,这似乎会导致错误? - jswny
编辑以搜索逗号。分号呢?您需要在正则表达式中指定允许出现在括号之间的字符,并转义那些具有正则表达式意义的字符。 - Paulo Arromba
还有一些其他的符号,比如()ºª&%$#"等等。但是添加它们很容易。我已经添加了一些,你可以随意添加或删除 ;) - Paulo Arromba
似乎现在应该可以工作了,但是由于某些原因,在数组中不允许 ',即使它出现在正则表达式中。 - jswny
似乎不需要转义'。 - Paulo Arromba

1
这个正则表达式可以工作。
([^?.]+[?.])(?:\s|$)

正则表达式演示

JS演示

Ideone演示

var str = 'This is sentence 1. This is sentence 2? This is sentence 3.';
var regex = /([^?.]+[?.])(?:\s|$)/gm;
var m;

while ((m = regex.exec(str)) !== null) {
    document.writeln(m[1] + '<br>');
}


看起来它从那个网站上运行正常。但是,当我将它放入我的JS文件中时,每个句子后面都会得到一个随机的空数组值,并且在数组中的每个句子之前都会卡住空格。 - jswny
现在将处理哪些空格..尝试使用 print 而不是 document.writeln..您在哪里使用它? - rock321987
出于某种原因,我仍然得到空数组值。我只是在我的网站页面上使用它来从字符串中拆分文本段落。然后我使用for循环打印每一行。 - jswny
@jswny 如果你使用这个正则表达式,就不需要拆分了。它匹配所有你想要的值。如果你在这个正则表达式上进行拆分,显然会得到一个空数组。 - rock321987
1
好的,我已经修复了以匹配现在的情况,这个可以工作了,非常感谢! - jswny
1
明白了,忘记了,抱歉 :P - jswny

0

也许这个可以验证您的数组项

\b.*?[?\.](?=\s|$)

Regular expression visualization

Debuggex演示


这只匹配我的字符串的最后一句话。我需要将其拆分为每个句子。 - jswny
这个怎么样?转换为非贪婪模式,根据您的情况,可以将 * 替换为 + - Redu
那只是返回一堆空格,然后是最后一句话。 - jswny
如果“last”句子在句号或问号后面没有尾随的空格,则您的正则表达式可能像这样被修改。 - Redu

0

我猜 .match 可以做到:

(?:\s?)(.*?[.?])

I.e.:

sentence = "This is sentence 1. This is sentence 2? This is sentence 3.";
result = sentence.match(/(?:\s?)(.*?[.?])/ig);
for (var i = 0; i < result.length; i++) {
   document.write(result[i]+"<br>");
}


0
这很俗气,但它能用:
var breakIntoSentences = function(s) {
  var l = [];
  s.replace(/[^.?]+.?/g, a => l.push(a));
  return l;
}

breakIntoSentences("how? who cares.")
["how?", " who cares."]

真正的工作原理是:RE匹配一个非标点符号的字符串,后面跟着某些内容。由于匹配是贪婪的,所以那个东西要么是标点符号,要么就是字符串的结尾。

这只会捕获一系列标点符号中的第一个,因此breakIntoSentences("how???? who cares...")也会返回["how?", " who cares."]。如果您想捕获所有标点符号,请使用/[^.?]+[.?]*/g作为RE。

编辑:哈哈哈:Wavvves教我使用match(),这就是replace/push所做的事情。每天都能学到新东西。

在其最简形式下,支持三个标点符号,并使用ES6语法,我们得到:

const breakIntoSentences = s => s.match(/[^.?,]+[.?,]*/g)

1
@rock321987 -- 我也是从wavvves那里复制过来的。现在已经修正了。 - Michael Lorton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接