3

我必须处理一个文本文件(电子书)。我想处理它,以便每行有一个句子(“换行符分隔的文件”,是吗?)。我将如何使用 sed UNIX 实用程序来完成这项任务?它是否具有“句子边界”的符号,就像“单词边界”的符号一样(我认为 GNU 版本有)。请注意,句子可以以句号、省略号、问号或感叹号结尾,最后两个组合在一起(例如,?、!、!?、!!!!! 都是有效的“句子终止符”)。输入文件的格式设置为某些句子包含必须删除的换行符。

我想到了一个脚本s/...|. |[!?]+ |/\n/g(为了更好地阅读而未转义)。但它不会从句子中删除换行符。

在 C# 中怎么样?如果我使用像 sed 这样的正则表达式会不会快得多?(我想不是)。还有其他更快的方法吗?

无论哪种方式(sed 或 C#)都可以。谢谢你。

4

5 回答 5

3

正则表达式是我使用了很长时间的一个不错的选择。

一个非常适合我的正则表达式是

 string[] sentences = Regex.Split(sentence, @"(?<=['""A-Za-z0-9][\.\!\?])\s+(?=[A-Z])");

但是,正则表达式效率不高。此外,尽管该逻辑适用于理想情况,但在生产环境中效果不佳。

例如,如果我的文字是,

美国是一个美妙的国家。大多数人都觉得住在那里很开心。

正则表达式方法将通过在每个周期拆分将其分类为 5 个句子。但我们知道,从逻辑上讲,它应该只分成两个句子。

这就是让我寻找机器学习技术的原因,最后 SharpNLP 对我来说效果很好。

 private string mModelPath = @"C:\Users\ATS\Documents\Visual Studio 2012\Projects\Google_page_speed_json\Google_page_speed_json\bin\Release\";
 private OpenNLP.Tools.SentenceDetect.MaximumEntropySentenceDetector mSentenceDetector;
 private string[] SplitSentences(string paragraph)
    {
        if (mSentenceDetector == null)
        {
            mSentenceDetector = new OpenNLP.Tools.SentenceDetect.EnglishMaximumEntropySentenceDetector(mModelPath + "EnglishSD.nbin");
        }

        return mSentenceDetector.SentenceDetect(paragraph);
    }

在此示例中,我使用了 SharpNLP,其中我使用了 EnglishSD.nbin - 一个用于句子检测的预训练模型。

现在,如果我在此方法上应用相同的输入,它将完美地将文本拆分为两个逻辑句子。

您甚至可以使用 SharpNLP 项目进行标记化、POSTag、Chuck 等。

要逐步将 SharpNLP 集成到您的 C# 应用程序中,请阅读我编写的详细文章。它将向您解释与代码片段的集成。

谢谢

于 2013-10-19T08:04:33.710 回答
1

句子分裂是一个重要的问题,已经开发了机器学习算法。[.\?!]+但是在大写字母和大写字母之间分割空格[A-Z]可能是一个很好的启发式方法。首先用 删除换行符tr,然后应用 RE:

tr '\r\n' ' ' | sed 's/\([.?!]\)\s\s*\([A-Z]\)/\1\n\2/g'

输出应该是每行一个句子。如果发现错误,请检查输出并优化 RE。(例如,mr. Ed会被错误地处理。也许编译一个这样的缩写列表。)

C#sed是否更快只能通过实验确定。

于 2011-04-11T11:50:56.910 回答
0

您感兴趣的任务通常被称为“句子分割”。正如 larsmans 所说,这是一个不平凡的问题,但启发式方法通常表现得相当好,至少对于英语来说是这样。

听起来您主要对英语感兴趣,因此已经介绍的正则表达式启发式可能足以满足您的需求。如果您想要一个更准确的解决方案(以稍微复杂一点为代价),您可以考虑使用开源 NLP 框架 LingPipe。我用 LingPipe 运气不错,我用过几次。

有关句子分割的详细教程,请参见http://alias-i.com/lingpipe/demos/tutorial/sentences/read-me.html

于 2011-04-18T20:09:06.223 回答
0

您可以查看我的教程http://code.google.com/p/graph-expression/wiki/SentenceSplitting 基本想法是在每次拆分时都有拆分字符和不可能的前置/后置条件。Tji 的简单启发式方法非常有效。

于 2011-04-11T22:10:55.780 回答
0

你可以使用这样的东西来提取句子:

var sentences = Regex.Matches(input, @"[\w ,]+[\.!?]+")
foreach (Match match in sentences)
{
  Console.WriteLine(match.Value);
}

这应该匹配包含单词、空格和逗号并以(任意数量的)句点、感叹号和问号结尾的句子。

于 2011-04-11T11:41:40.380 回答