【问题标题】:PHP trying to split paragraph into sentences. Keep punctuationPHP 试图将段落拆分成句子。保留标点符号
【发布时间】:2012-09-22 20:43:51
【问题描述】:

基本上我会读一段充满各种标点符号的段落 如 ! ? . ; "并将它们分成句子。 我面临的问题是想出一种方法,将它们拆分成带有完整标点符号的句子,同时考虑对话中的引用

例如段落:

一天早上,当格雷戈尔·萨姆萨从噩梦中醒来时,他发现 自己在床上变成了可怕的害虫。 “有什么 发生了!?”他问自己。“我……不知道。”萨姆萨说,“也许 这是一个噩梦。”他像盔甲一样躺在他的背上,如果他抬起 他的头稍微有点他能看到他棕色的腹部,略呈圆拱形, 被拱门分成坚硬的部分。

需要这样拆分

[0] One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. 

[1] "What has happened!?" he asked himself.

[2] "I... don't know." said Samsa, "Maybe this is a bad dream."

等等。

目前我只是在使用explode

$sentences = explode(".", $sourceWork);

并且仅按句点将其拆分并在末尾附加一个。我知道这与我想要的相去甚远,但我不太确定从哪里开始处理这个问题。如果有人至少可以为我指出在哪里寻找很棒的想法的正确方向。

提前致谢!

【问题讨论】:

  • “昨天我去过拉什莫尔山。”
  • @Ozerich:是的,几乎不可能准确地解析自然语言。尝试越多,越会发现不符合规则的示例。

标签: php regex


【解决方案1】:

这是我所拥有的:

<?php

/**
 * @param string $str                          String to split
 * @param string $end_of_sentence_characters   Characters which represent the end of the sentence. Should be a string with no spaces (".,!?")
 *
 * @return array
 */
function split_sentences($str, $end_of_sentence_characters) {
    $inside_quotes = false;
    $buffer = "";
    $result = array();
    for ($i = 0; $i < strlen($str); $i++) {
        $buffer .= $str[$i];
        if ($str[$i] === '"') {
            $inside_quotes = !$inside_quotes;
        }
        if (!$inside_quotes) {
            if (preg_match("/[$end_of_sentence_characters]/", $str[$i])) {
                $result[] = $buffer;
                $buffer = "";
            }
        }
    }
    return $result;
}

$str = <<<STR
One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. "What has happened!?" he asked himself. "I... don't know." said Samsa, "Maybe this is a bad dream." He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.
STR;

var_dump(split_sentences($str, "."));

【讨论】:

  • @Ozerich:用英语区分每一个细节是不可能的。你如何判断它是否是判刑结束? “如果它之前有一个先生或夫人,这不是结束)。但是还有一个你已经忘记的博士,还有教授。它没有尽头。你只需要找到你妥协的那个地方,继续前进。
  • 是的,我知道这是不可能的,这意味着你的解决方案,因为我的解决方案还没有准备好投入生产:)
  • @Ozerich:OP 要求排除引号内的标点符号,这就是我给他的。我很确定他以前的情况更糟(因为引号中的内容不会幸免),因此,此解决方案适用于 OP 需求。 OP 应该意识到英语(不是 PHP)的简单限制,它可能会在意想不到的地方产生一段时间。这不是 PHP 问题。
【解决方案2】:
preg_split('/[.?!]/',$sourceWork);

这是非常简单的正则表达式,但我认为你的任务是不可能的。

【讨论】:

  • [2] "I... don't know." said Samsa, "Maybe this is a bad dream." - 它会起作用吗? ...
  • 我能做到。但唯一的问题是它不能解释对话中的标点符号。我会卡在句子开头的随机引号中。
【解决方案3】:

您需要手动检查您的字符串并进行爆炸。跟踪引用计数,如果是奇数不要中断,这里有一个简单的想法:

    <?
//$str = 'AAA. BBB. "CCC." DDD. EEE. "FFF. GGG. HHH".';
$str = 'One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. "What has happened!?" he asked himself. "I... don\'t know." said Samsa, "Maybe this is a bad dream." He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.';
$last_dot=0;
$quotation=0;
$explode_list = Array();
for($i=0;$i < strlen($str);$i++)
{
    $char = substr($str,$i,1);//get the currect character
    if($char == '"') $quotation++;//track quotation
    if($quotation%2==1) continue;//nothing to do so go back

    if($char == '.')
    {
        echo "char is $char $last_dot<br/>";
         $explode_list[]=(substr($str,$last_dot,$i+1-$last_dot));
         $last_dot = $i+1;
    }
}

echo "testing:<pre>";
print_r($explode_list);;

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-07
  • 2013-08-13
  • 2013-05-21
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
相关资源
最近更新 更多