【问题标题】:Removing a block of text with regex, matching first occurrences only使用正则表达式删除文本块,仅匹配第一次出现
【发布时间】:2015-04-29 01:21:43
【问题描述】:

我需要使用正则表达式从生成的脚本中删除存储过程。比如我需要删除usp_Remove:

...
GO
/****** Object:  StoredProcedure [dbo].[usp_Remove] ******/
...
GO
/****** Object:  StoredProcedure [dbo].[usp_Keep]  ******/
...
GO

我尝试了以下正则表达式:

\/*\*\*\*\*\*\* Object:  StoredProcedure \[dbo\]\.\[usp_Remove\][\s\S]*GO

正确选择文本的开头。但它匹配所有内容,直到最后一个“GO”,我需要它匹配直到第一次出现“GO”,以便仅删除该存储过程。任何帮助将不胜感激!

【问题讨论】:

  • 请显示您想要的输出。

标签: c# regex


【解决方案1】:

我会使用惰性匹配以避免过度匹配,并使用积极的前瞻来仅捕获存储过程:

(?si)/\*{6}\s+Object:\s+StoredProcedure\s+\[dbo\]\.\[usp_Remove\]\s+\*{6}\/.*?(?=GO)

示例代码:

var txt = "YOUR_TXT";
var rx = new Regex(@"/\*{6}\s+Object:\s+StoredProcedure\s+\[dbo\]\.\[usp_Remove\]\s+\*{6}\/.*?(?=GO)", RegexOptions.Singleline | RegexOptions.Ignorecase);
var result = rx.Replace(txt, string.Empty);

快递:

【讨论】:

  • 我感谢所有的答案,他们真的很有帮助。但是 (?=GO) 的解释确实做到了。谢谢!
【解决方案2】:

这是一个使用正则表达式选项的模式 Multiline(指定 ^ 将在行的开头)和 Singleline 告诉 . 包含空白字符:

string text = @"...
GO
/****** Object:  StoredProcedure [dbo].[usp_Remove] ******/
...
GO
/****** Object:  StoredProcedure [dbo].[usp_Keep]  ******/
...
GO";

Console.WriteLine (Regex.Replace(text,
                                 @"(^\/.+usp_Remove.+?GO)",
                                 string.Empty,
                                 RegexOptions.Multiline | RegexOptions.Singleline ));

结果

... 
GO

/****** Object:  StoredProcedure [dbo].[usp_Keep]  ******/ 
... 
GO

【讨论】:

    【解决方案3】:

    你可能想试试这个:

    string resultString = null;
    try {
        resultString = Regex.Replace(subjectString, @"\/.*?\[usp_Remove\].*?$\s+GO", "", RegexOptions.Singleline | RegexOptions.Multiline);
    } catch (ArgumentException ex) {
        // Syntax error in the regular expression
    }
    

    输出:

    ...
    GO
    
    /****** Object:  StoredProcedure [dbo].[usp_Keep]  ******/
    ...
    GO
    

    DEMO


    正则表达式解释:

    \/.*?\[usp_Remove\].*?$\s+GO
    
    Options: Case sensitive; Exact spacing; Dot matches line breaks; ^$ match at line breaks; Numbered capture
    
    Match the character “/” literally «\/»
    Match any single character «.*?»
       Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
    Match the character “[” literally «\[»
    Match the character string “usp_Remove” literally (case sensitive) «usp_Remove»
    Match the character “]” literally «\]»
    Match any single character «.*?»
       Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
    Assert position at the end of a line (at the end of the string or before a line break character) (line feed) «$»
    Match a single character that is a “whitespace character” (any Unicode separator, tab, line feed, carriage return, vertical tab, form feed, next line) «\s+»
       Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
    Match the character string “GO” literally (case sensitive) «GO»
    

    【讨论】:

    • 他想从包含uspRemove的评论中删除到下一个Go。
    • @OmegaMan 明白了,谢谢!
    【解决方案4】:

    这是 GREEDY 正则表达式模式的产物。 查看更多信息:http://stackoverflow.com/a/5319978/4408842

    我决定只添加一个否定的前瞻 ((?!GO)) 以确保“/***”之间的块内没有其他“GO”语句*...“ 去”。 请记住,您要取出的 SQL 脚本块本身不能有另一个“GO”语句,否则此方法将在“GO”处停止

    我还重写了您的 [\s\S]* 限定符 - 这肯定是一个贪婪的,寻找任意数量的空白或非空白字符(意思是,绝对在找到模式的结尾之前尽可能多的东西),我已经将 \*\*\*\*\*\* 重写为 \*{6} 为更容易阅读。

    \/\*{6} Object:  StoredProcedure \[dbo\]\.\[usp_Remove\].{0,10}\*{6}\/(?!GO)[.\n]*GO
    

    【讨论】:

      猜你喜欢
      • 2018-06-28
      • 1970-01-01
      • 2016-03-18
      • 2021-11-05
      • 2015-03-15
      • 2022-08-13
      • 2019-04-09
      • 1970-01-01
      相关资源
      最近更新 更多