从文本字符串中提取第一个句子

时间:2010-09-24 14:49:06

标签: regex string

是否有一个简单的技巧来隔离大量文本中的第一个句子? (也许使用正则表达式。)

搜索第一个完整停车位。“不起作用,像“美国”这样的缩写词。将搞砸了。

(可能没有正确答案。)

10 个答案:

答案 0 :(得分:9)

没有。没有简单的伎俩。要正确执行此操作,您需要对文本进行语法分析。没人能做到这一点。至少还没有。至少不是100%的时间。主要是因为它还需要对文本进行语义分析。你看,与在学校里教你语法的语言学家所认为的相比,构成一个句子的内容很难用计算机可以遵循的一套规则来概括而不理解文本。

在接下来的几年中寻找计算语言学。也许到那时会有一条捷径?

但你可以近距离接触。

我可能会尝试寻找第一个句号,问号或感叹号,然后是空格。

/^(.*?)[.?!]\s/

(.*?)是一个非贪婪的正则表达式,以确保你真的只找到第一句话。

答案 1 :(得分:5)

你愿意付钱吗?如果是亚马逊的机械土耳其人以任何速度向真人发送任务,那么每次更新可以说是0.01美元。至少它打败了两年的计算语言学。 ; - )

答案 2 :(得分:4)

这不能以有保证的方式完成,但这会让你非常接近一个相对简单的表达方式:

/(^.*?[a-z]{2,}[.!?])\s+\W*[A-Z]/

从该行的开头(^)开始,它非贪婪地查找以至少两个小写字母(.*?)结尾的任意数量的任意字符([a-z]{2,})和句点,问号或感叹号([.!?]),后跟一个或多个空格(\s+),零个或多个非单词字符,例如左括号(\W*)和大写字母([A-Z])。

这将避免由于首字母缩略词而导致的过早截断,假设它们是:

  • 大写,如“U.S.A。”
  • 是小写但是单独的字母,如“eg”或“即”。
  • 或后跟小写字母,如“this abbr。代表缩写。”

一个缺点是,如果一个句子以一个标点的大写首字母缩写词或缩写词结尾,它就不会停止,但是由于它的简单性和有效性,这似乎是一个公平的权衡。

答案 3 :(得分:1)

通常,您将查找不遵循大写字母的第一个句号。但这不适用于一些缩写。

没有神奇的解决方案......您可以列出所有缩写并在完全停止后忽略它们。

答案 4 :(得分:1)

如前所述,没有简单的解决方案。

正则表达式的更高版本可以是:/^(.*?(?<!\b\w)[.?!])\s+[A-Z0-9]/。它不会停在句子中间的缩写(但也不会,如果它们在句子末尾......),下一句话必须以大写字母或数字开头......

如果你知道一个你不希望你的正则表达式停留的首字母缩略词列表,你可以通过以下方式添加它们:/^(.*?(?<!\b\w|U\.S\.A|eg)[.?!])\s+[A-Z0-9]/

如果您知道要使用的语言,可能会有一些自然语言分析(NLP)工具包 - 但这超出了本问题的范围。

答案 5 :(得分:1)

尝试使用诸如Splitta(http://code.google.com/p/splitta/)之类的Bayes解决方案或在Ruby世界中使用Tactful Tokenizer(https://github.com/SlyShy/Tactful_Tokenizer)。

答案 6 :(得分:0)

使用纯文本字符串并不保证这样做,但是使用带有一些屏蔽的字符串,例如,如果你的字符串在每行或句子的末尾有\ n,你可以用它来确定行的结尾除此之外,你必须猜测它。

答案 7 :(得分:0)

你能否认为首字母缩略词在句号之间没有空格?如果是这样,这将有效:

string.split('. ').first

e.g。

s = "Lorem ipsum dolor sit amet, U.S.A adipiscing elit. Phasellus nulla magna, suscipit dapibus bibendum sit amet."
s.split('. ').first

=> "Lorem ipsum dolor sit amet, U.S.A adipiscing elit"

请注意,它会删除尾随句点。

答案 8 :(得分:0)

这是我的解决方案。您还可以找到有效的Codepen here

HTML

<div id="original">
   Lorem ipsum dolor sit amet, U.S.A adipiscing elit. Phasellus nulla magna, suscipit dapibus bibendum sit amet.
</div></br> 

<div id="results"></div>

<强>的JavaScript

var s = document.getElementById('original').innerHTML

var t = s.split('. ', 1)[0]

console.log(t)

document.getElementById('results').innerHTML = t

答案 9 :(得分:0)

这是我的解决方法。

该方法考虑了句子中的点号:U.S.A等。
还为结果字符串的最小长度添加了一个可选参数。

/// <summary>
/// Gets the first sentence from the text.
/// </summary>
/// <param name="text">The text.</param>
/// <param name="minLength">The minimum length of the sentence.</param>
public static string FirstSentence(this string text, int minLength = 10)
{
    if (string.IsNullOrWhiteSpace(text))
    {
        return string.Empty;
    }

    var sentences = Regex.Split(text, @"(.[^\.\!\?]*(?>\.[^\s\.][^\.\!\?]+)*[\.\!\?]*)", RegexOptions.Multiline)
        .Where(s => !string.IsNullOrEmpty(s))
        .Select(s => s.Trim())
        .ToArray();

    var result = string.Empty;

    foreach (var s in sentences)
    {
        result = $"{result} {s}".Trim();

        if (result.Length >= minLength)
        {
            break;
        }
    }

    return result;
}