正则表达式提取多个句子,同时丢弃特定句子

时间:2012-04-07 20:26:16

标签: c# regex

在:preferences = 'Hello my name is paul. I hate puzzles.'中 我想提取Hello my name is paul.

在:preferences = 'Salutations my name is richard. I love pizza. I hate rain.'中 我想提取Salutations my name is richard. I love pizza.

在:preferences = 'Hi my name is bob. I enjoy ice cream.'中 我想提取Hi my name is bob. I enjoy ice cream.

换句话说,我想

  • 始终放弃preferences = '
  • 丢弃任何最后句子(由.分隔),其中包含hate(如果有)
  • 弃掉最终的'

我的问题是我的正则表达式在第一个.停止,并且不提取后续句子。

感谢。

4 个答案:

答案 0 :(得分:2)

您可以使用正则表达式实现您想要的目标:

^preferences\s*=\s*'(.*?\.)(?:[^.]*\bhate\b[^.]*\.)?'$

那个并不太棘手:

  • (.*?\.) - 匹配您的预期输出,该输出将在组$1中捕获。模式匹配“句子”(如您所定义的),但懒惰(*?),尽可能少。
  • (?:[^.]*\bhate\b[^.]*\.)? - 可选地匹配最后一句,但前提是它包含“讨厌”。如果它可以匹配,并且它是最后一个句子,匹配的引擎将不会回溯,并且最后一个句子将不包括在捕获的组中。

以下是Rubular中的一个工作示例:http://www.rubular.com/r/qTuMmB3ySj
(我在几个地方添加了\r\n,以避免[^.]匹配新行

老实说,如果你能避免,你可以做得比这里的单个正则表达更好。

答案 1 :(得分:1)

虽然这不是使用RegEx,但它将实现您的目标

List<string> resultsList = new List<string);


for(int i = 0; i < preferences.Count; i++)
{
    List<string> tempList = new List<string);
    //creating the substring eliminates the "preferences = '" as well as the "'" at end of string
    //this line also splits each string from the preferences string list into the tempList array
    tempList = preferences[i].Substring(15, preferences[i].Length - 15 - 1).Split('.').ToList();

    string buildFinalString = "";

    //traverse tempList and only add string to buildFinalString if it does not contain "hate"
    foreach(string x in tempList)
    {
        if(!x.Contains("hate").ToUpper() || !x.Contains("hate").ToLower())
        {
             buildFinalString = buildFinalString + " " + x;
        }
    }
    resultsList.Add(buildFinalString);
}

或者如果您只想检查“tempList”数组中最后一个字符串是否为hate,那么这也是可能的......

答案 2 :(得分:1)

我用2个正则表达式做到了。第一个用于剥离preferences = '...',第二个用于删除任何带有“hate”一词的句子。第二个正则表达式使用正向lookbehind用带有空字符串的关键字替换setntences。

String[] tests = {
    "preferences = 'Hello my name is Paul. I hate puzzles.'",
    "preferences = 'Salutations my name is Richard. I love pizza. I hate rain.'",
    "preferences = 'Hi my name is Bob. Regex turns me on.'"};
var re1 = new Regex("preferences = '(.*)'");
var re2 = new Regex("([^\\.]+(?<=.*\\bhate\\b.*)).\\s*");

for (int i=0; i < tests.Length; i++)
{
    Console.WriteLine("{0}: {1}", i, tests[i]);
    var m = re1.Match(tests[i]);
    if (m.Success)
    {
        var s = m.Groups[1].ToString();
        s = re2.Replace(s,"");
        Console.WriteLine("   {1}", i, s);
    }
    Console.WriteLine();
}

这可能不是您想要的,因为您要求仅删除最后一个句子,如果它包含标志词。但如果你真的想要删除最后一句话,如果它包含单词,那么很容易调整。在这种情况下,您只需要将一个$附加到re2的末尾。

答案 3 :(得分:0)

其中一个可能有用 -

Match [1] buffer

中的结果
preferences\s*=\s*'([^']*?)(?:(?<=[.'])[^.']*hate[^.']*\.\s*)?'

Match [1] buffer

中的结果
preferences\s*=\s*'([^']*?)(?=(?<=[.'])[^.']*hate[^.']*\.\s*'|')

(仅限.Net)
Match [0] buffer

中的结果
(?<=preferences\s*=\s*')[^']*?(?=(?<=[.'])[^.']*hate[^.']*\.\s*'|')

编辑:不使用\ b围绕'hate',也不使用开始/结束构造^ $,如果你需要的话,随意添加它们。作为一个方面没有,它的迷惑如何在分隔具有自由格式文本的字符串变量的上下文中使用撇号和句号。