2012-01-09 55 views
3

考虑这段文字如何将段落拆分成句号(。)分隔的句子,除非句号是缩写的一部分?

保护组织称20年禁令是美国偶像的重要保护。采矿业和一些共和党议员表示,这对亚利桑那州的经济和国家的能源独立是不利的。“尽管采矿业面临巨大压力,但总统和秘书萨拉扎并没有退缩,”美国公共土地总监简·达诺维茨说。为皮尤环境集团。

在上面的例子中,它很容易在句点(。)中分割句子,但它在美国处理句号时会导致错误的结果。假设我有一个缩写列表,如

String abbrev[] ={"u.s.a", "u.a.e", "u.k", "p.r.c","u.s.s.r", }; 
String regex= "\\."; 
Pattern pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE); 
Matcher matcher = pattern.matcher(sx); 
int beginIndex=0; 

// Check all occurance 
int index=0; 
while (matcher.find()) { 
    System.out.print("Start index: " + matcher.start()); 
    System.out.print(" End index: " + matcher.end() + " "); 

    String group=matcher.group(); 
    System.out.println("group: " + group); 
    int dotIndex= group.indexOf("."); 
    String sub= sx.substring(beginIndex, matcher.start()+dotIndex); 
    beginIndex= matcher.start()+dotIndex; 

    System.out.println(sub); 
}    

我可以做一个蛮力匹配周围dotIndex所有的缩写。有更好的方法吗?

+0

你能利用正规句子后面的空间,还是有其他边界条件? – 2012-01-09 20:12:33

+0

@JoshG:我想过,但其他情况如何呢?这个例子有'eg'和一个空格。您需要根据之前的内容来验证(或否定),比如'(?<!\。[az])\。\ s'(需要一个句点和一个空格,前面没有句号和一个字母) – 2012-01-09 20:14:44

+1

你打算如何区分句子中间的缩写与句尾的缩写?例如,“我住在美国” – 2012-01-09 20:45:31

回答

2

我最好的猜测会是这样的:(?<!\.[a-zA-Z])\.(?![a-zA-Z]\.)这将转化为:

(?<!\.[a-zA-Z]) # can't be preceded by a period followed by a single letter 
\. 
(?![a-zA-Z]\.)  # nor can it be followed by a letter and another preiod 

然后,您可以执行从那里更换。如果你需要赶上引号内期间,虽然,这是不在上面的图案

Demo

这将需要更多的努力。

+0

缩写与 – insipid 2012-01-09 20:24:10

+0

@insipid有什么关系:你可以改变量词来接受“{1,2}”(基于句子通常不会以双字母单词结尾),或者可以在每个实例并在进行解析之前对照例外列表(包括'vs'的缩写)进行测试。 – 2012-01-09 20:32:45

+0

@布拉德:还有什么?(如英寸)?这可以是任何一个。将它添加到白名单是不够的。 – cHao 2012-02-03 21:55:31

1

依靠正则表达式无法解决此问题。要知道一个句子是否在任何特定的时期结束并不简单。缩写可能是也可能不是句子的结尾。椭圆可以写成三个时期(或者,在某些情况下,四个,取决于主流风格)。句子有时会在标记句子结尾的句号之后出现的引号之后结束(再次取决于流行风格)。

大多数情况下,您都可以使用启发式方法来获得答案。但它更像是一个统计问题而不是正则表达式问题。