php - 优化句子清理器的正则表达式

标签 php regex preg-replace

这是一个句子 sanitizer 。

function sanitize_sentence($string) {
    $pats = array(
    '/([.!?]\s{2}),/',      # Abc.  ,Def
    '/\.+(,)/',             # ......,
    '/(!|\?)\1+/',          # abc!!!!!!!!, abc?????????
    '/\s+(,)/',             # abc   , def
    '/([a-zA-Z])\1\1/');    # greeeeeeen
    $fixed = preg_replace($pats,'$1',$string); # apply pats
    $fixed = preg_replace('/(?:(?<=\s)|^)[^a-z0-9]+(?:(?=\s)|$)/i', '',$fixed); # bad chunks
    $fixed = preg_replace( '/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already
    $fixed = preg_replace( '/[^a-zA-Z0-9!?.]+$/', '.', $fixed); # end of string must end in period
    $fixed = preg_replace('/,(?!\s)/',', ',$fixed); # spaces after commas
    return $fixed;
}

这是测试句子:

hello [[[[[[]]]]]] friend.....? how are you [}}}}}}

它应该返回:

hello friend.....? how are you

但它正在返回:

hello friend. .. .. ? how are you.

所以有两个问题,我找不到解决方案:

  1. 这组句点被分成“.. ..”因为某些原因。它们应保留为问号旁边的“.....”。
  2. 如果字符串中的任意位置至少存在以下字符之一,则字符串的末尾必须仅以句点结束并且仅:!?,.(如果字符串中至少找不到这些字符之一,因此不应执行 preg_replace)

第二个问题的示例:

This sentence doesn't need an ending period because the mentioned characters are nowhere to be found

This other sentence, needs it! Why? Because it contains at least one of the mentioned characters

(当然,只有当结束句点尚不存在时才应放置)

感谢您的帮助!

最佳答案

这是您第一个问题的答案。倒数第三个替换是问题所在:

$fixed = preg_replace( '/([!?,.])(\S)/', '$1 $2', $fixed); # spaces after punctuation, if it doesn't exist already

它将第一个句点与字符类匹配,将第二个句点匹配为非空格字符。然后插入一个空格。由于匹配不能重叠,因此它将匹配第三个和第四个句点并插入一个空格等。这可能最好像这样修复:

$fixed = preg_replace( '/[!?,.](?![!?,.\s])/', '$0 ', $fixed);

以下是如何满足第二个要求(替换倒数第二个 preg_replace):

$fixed = trim($fixed);
$fixed = preg_replace( '/[!?.,].*(?<![.!?])$/', '$0.', $fixed);

首先,我们去掉前导和尾随空格,将这个问题与尾随句点分开。然后 preg_replace 将尝试在字符串中查找标点符号,如果找到,它将匹配所有内容,直到字符串末尾。替换将匹配放回原处并附加句点。注意消极的后向观察。它断言字符串尚未以句子结束标点符号结尾。

关于php - 优化句子清理器的正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13444836/

相关文章:

替换字符串中的 PHP preg_quote

php - preg_replace 和 preg_match 阿拉伯字符

php - 如何创建包含特殊字符的 XML 文件

php - 如何获取每个类别的最新帖子

c# - 从基于索引的正则表达式中获取反向引用基于名称的正则表达式

regex - Excel VBA正则表达式错误

php - 正则表达式替换网页中的单词

php - 解析 bbcode 中的多个列表?

javascript - 想要使用Javascript(ajax)和PHP执行数据库操作而无需重新加载页面

php - 正则表达式匹配以 %% 开头和结尾的字符串