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

本文关键字:句子 一个 提取 正则表达式 | 更新日期: 2023-09-27 18:30:26

In: 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的最后一句(由.分隔),如果存在
  • 放弃最终'
我的

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

谢谢。

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

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

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

那个不是太棘手:

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

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

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

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

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 个正则表达式做到了。第一种是用来剥离preferences = '...',第二种是去掉任何带有"恨"字的句子。 第二个正则表达式使用正反转来用空字符串替换带有关键字的设置。

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 的末尾附加一个 $。

其中之一可能有效 -

匹配[1] 缓冲区中的结果

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

匹配[1] 缓冲区中的结果

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

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

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

编辑:不要在"hate"周围使用''b,也不使用开始/结束构造^$,如果需要,请随时添加它们。作为一面,在分隔包含自由格式文本的字符串变量的上下文中如何使用撇号和句点令人费解。