我正在尝试将文本文件解析为以句点结尾的句子,但是像霍普金斯先生这样的名字在匹配句点时会发出错误的警报。
什么正则表达式标识“。” 但不是“先生”
为了奖金,我也在使用!找到句子的结尾,所以我当前的正则表达式是 /(!/./ 我也希望得到一个包含我的 ! 的答案。
我正在尝试将文本文件解析为以句点结尾的句子,但是像霍普金斯先生这样的名字在匹配句点时会发出错误的警报。
什么正则表达式标识“。” 但不是“先生”
为了奖金,我也在使用!找到句子的结尾,所以我当前的正则表达式是 /(!/./ 我也希望得到一个包含我的 ! 的答案。
用负面的目光看背后。
(?<!Mr|Mrs|Dr|Ms)\.
仅当它不在Mr
, Mrs
,Dr
或Ms
<?
$str = "This is Mr. Someone and Mrs. Somebody. They are here to meet Dr. SomeoneElse.";
$str = preg_replace("/(?<!Mr|Mrs|Dr|Ms)\\./", "\n", $str);
echo($str);
?>
//outputs:
This is Mr. Someone and Mrs. Somebody
They are here to meet Dr. SomeoneElse
这不能用任何简单的机制来完成。这是无可救药的模棱两可。句子可以以缩写结尾,在这种情况下,它们不会用两个句点书写。
请参阅Unicode TR29。另请参阅 ICU 开源库,其中包含一个基本实现。
你的句子后面总是跟两个空格吗?如果是这样,您可以检查一下...
/\.\s{2}/
并结合句子标点符号的另一端:
/[\.\!\?]\s{2}/
您还可以检查可能指示句子结尾的其他内容,例如下一个单词是否大写,是否后跟回车等。但充其量您只能做出有根据的猜测,正如上面所指出的,这个时期太模棱两可了。
正则表达式(?<=[\.\!\?]\s[A-Z])
在经过测试后几乎可以工作,但遗憾的是它在之前的匹配中留下了大写字母。解决此问题的方法是将该字母从上一场比赛中删除,同时将其添加回比赛本身。
例子:
//the string
string s = "The fox jumps over the dog. The dog jumps over the fox.";
string[] answer = Regex.Split(@"(?<=[\.\!\?]\s[A-Z])");
Console.WriteLine(answer);
输出将是:["The fox jumps over the dog. T","he dog jumps over the fox."]
要解决这个问题:
//make sure there is a split
if (lines.Length > 1)
{
for (int i = 0; i < lines.Length; i++)
{
//store letter
char misplacedLetter = lines[i].TrimEnd().Last();
//remove letter
lines[i] = lines[i].Substring(0,lines[i].Length-1);
//place on front of next sentence.
lines[i + 1] = misplacedLetter + lines[i + 1];
}
}
这对我很有效。(您可以选择缓存lines[i]
而不是一遍又一遍地访问它)