2

在: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 = '
  • 丢弃任何包含单词in的最后一句话(由 分隔.) ,如果存在的话。hate
  • 丢弃决赛'

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

谢谢。

4

4 回答 4

2

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

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

那不是太棘手:

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

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

不过老实说,如果可以避免的话,您可以比使用单个正则表达式做得更好。

于 2012-04-07T21:23:21.183 回答
1

虽然这不使用正则表达式,但它将实现您的目标

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”数组中的最后一个字符串是否有单词 hat,这也是可能的......

于 2012-04-07T21:16:12.357 回答
1

我用2个正则表达式做到了。第一个用于preferences = '...'去除 ,第二个用于消除任何带有“恨”字的句子。第二个正则表达式使用积极的后向查找来用空字符串的关键字替换 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 的末尾附加一个 $。

于 2012-04-07T21:32:19.283 回答
0

其中之一可能有效 -

结果匹配 [1] 缓冲区

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

或者

结果匹配 [1] 缓冲区

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

或者

(仅限 .Net)
匹配 [0] 缓冲区中的结果

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

编辑:不要在“仇恨”周围使用 \b,也不要开始/结束构造 ^$,如果你需要的话,请随意添加它们。另一方面,令人费解的是,撇号和句点如何在分隔包含自由格式文本的字符串变量的上下文中使用。

于 2012-04-07T22:04:30.657 回答