0

这个问题是我之前问题的延续:

正则表达式排除学术头衔

我想使用带有字符点(。)的正则表达式将段落字符串拆分为句子数组。下一个问题是关于数字的。

这是一个例子:

在 2013 年。您好,安德烈先生,您的钱是 40.000 印尼盾。

当然正确的输出:

数组([0] => 今年 2013 [1] => 你好,安德烈先生,你的钱是 40.000 印尼盾)

我之前的问题已经解决了标题问题(先生)。我试过添加数字的正则表达式,但仍然不起作用。

我没有工作的代码:

$titles_number=array('(^[0-9]*)','(?<!Mr)', '(?<!Mrs)', '(?<!Ms)');
$sentences=preg_split('/('.implode('',$titles_number).')\./',$text);
print_r($sentences);

我可以一击做到这一点(一个正则表达式来解决两个问题)吗?如果我做不到,请告诉我。提前致谢

4

2 回答 2

1

这将更容易完成preg_match_all()

preg_match_all(
    '/[^\s.][^.]*(?:\.(?:(?<=Prof\.|Dr\.|Mr\.|Mrs\.|Ms\.)|(?=\d))[^.]*)*\./',
    $subject, $result, PREG_PATTERN_ORDER);
print_r($result[0]);

解释:

  • [^\s.]匹配下一个非空白字符(即跳过句子之间的任何空白)
  • [^.]*吞噬任何非点字符
  • \.匹配一个点 IF...
  • (?<=Prof\.|Dr\.|Mr\.|Mrs\.|Ms\.)...这是敬语的一部分...
  • (?=\d)...或数字的一部分

笔记:

  1. (?<=Prof\.|Dr\.|Mr\.|Mrs\.|Ms\.)是合法的,因为交替是在顶层。也就是说,它就像几个离散的后视,每个都有固定的长度。这就是为什么我不得不\.在每个分支中重复而不是使用(?<=(?:Prof|Dr|Mr|Mrs|Ms)\.).

  2. \.(?=\d)似乎足以识别作为数字一部分的点。如果您确实必须检查点前后的数字,则可以(?=(?<=\d\.)\d)改用。

  3. 如果这是针对比作业问题更严重的问题,您应该丢弃正则表达式并寻找自然语言处理库。尽管这一切都很粗糙,但它非常接近正则表达式所能做的极限。

于 2013-05-02T04:48:38.903 回答
0

如果您注意到句子末尾的每个点后跟空格/制表符/换行符或字符串末尾,则可以避免数字问题(可能还有其他问题):

$titles=array('(?<!Mr)', '(?<!Mrs)', '(?<!Ms)');
$sentences=preg_split('/('.implode('',$titles).')\.(?=\s|$)/',$text);
print_r($sentences);
于 2013-05-02T04:19:26.947 回答