【问题标题】:Remove single line comment but not the string which is enclosed by single quote删除单行注释,但不删除单引号括起来的字符串
【发布时间】:2016-08-15 21:04:20
【问题描述】:

我正在创建一个示例代码,它解析一个 SQL 文件,其中我有 SQL 和一个注释代码块,例如:

-- CREATE PROCEDURE
/* 
 Cleaned By : Tej Kiran
 Cleaned On : 05/12/2009 
 -- Procedure [ChambalSchedules] 
*/ 
CREATE procedure [dbo].[ChambalSchedules] 
( 
 @dyid INT = -1, 
 @dy VARCHAR(10) = '', 
 @yr VARCHAR(10) = '', 
 @dt DATETIME = '', 
 @HID INT = 0, 
 @HsID INT = 0, 
 @CID INT = 0, 
 @ScId INT = 0 
) 
AS 
BEGIN 
 DECLARE @BLID BIT 
 DECLARE @BsID BIT 
 DECLARE @BTID BIT 
 DECLARE @BShId BIT 
 SET @BLID = 0 
 SET @BsID = 0 
 SET @BTID = 0 
 SET @BShId = 0 
...
...
...
 SELECT 
 ShID 
 , ShType 
 , ISNULL(list,'---') AS List
 , Dy 
 , ChambalID 
 , CTypeID 
 FROM #testing1
 WHERE 
 Day = @dyid 
 ORDER BY 
 Day 
 ,ShID 
... .
...
END;

我正在使用 Java 来解析这样的查询。我想清理以-- 开头并以\n 结尾但不想删除引号之间的内容的单行注释:'text -- text '

我使用了以下正则表达式:

qry= qry.replaceAll("(\s--.*)|((m?)^--.*\n)","");

它在 http://regexr.com/ 中运行良好,但在我的 Java 代码中它也在删除 '---'

qry= qry.replaceAll("(?m)(--.*\\n)", "");

请建议正确的正则表达式。

我有以下几种情况:

  • 案例 1:行以 -- 开头,之后它可能在 --\n 之间有任何字符或特殊字符(新行字符)

    -- This is my comment line should be removed

  • 案例2:行开始其他代码,行尾有注释。

    Select * from Table; -- GetListFrom table\n

    • 注意:我想删除-- GetListFrom table\n
  • 案例 3:如果行在单引号之间包含 --,则什么也不做。

    SELECT ShID , ShType , ISNULL(list,'---') AS list , Dy , chambalID , CTypeID FROM #testing1 WHERE Dy = @dyid ORDER BY Day ,ShID

    • 在这种情况下,不应删除任何内容。

请提出正确的方法。

【问题讨论】:

  • 请尝试以下模式(\n|^)\s*--.*[^']($|\n)。它还包括注释符号前的选项空格。如果不需要,请删除此部分。
  • 但在这种情况下,您必须用\n 或空格替换此字符串,具体取决于注释行的位置(第一行、最后一行或中间的一行)。上面的正则表达式将只允许您删除从行开始的 cmets。
  • 正确的做法是不要使用正则表达式。而是进行完整的 SQL 词法分析。例如考虑'a string' -- 'part of comment'
  • @Henry 同意。为了处理主题中提到的所有案例,应该分析整个查询。
  • a -- sql 注释行在 JDBC 中使用时真的很混乱(它会解决您的整个查询!)。我之前遇到过这个问题,听起来很痛苦,我不得不手动编辑查询。如果您绝对需要保留 cmets,我建议您使用 /* */ 评论

标签: java regex string parsing


【解决方案1】:

使用纯正则表达式解析如此复杂的内容的最大问题之一是效率。所以我放弃了这个想法,转而采用混合解决方案。

我假设您的大多数行中的任何地方都没有--。一个Scanner可以用来获取每一行,很简单看看有没有--存在:

Scanner getLine = new Scanner(qry);
while(getLine.hasNextLine()){
    String line = getLine.nextLine();
    if(line.contains("--")){
        // replacement happens here
    }
}

速度如此之快,而且可读性也很强。接下来,我们可以使用正则表达式:

line.replace("^((?:(?:'[^']*')|[^'-])*)--.*", "$1")

现在,当正则表达式匹配时,它会捕获整行。这就是为什么需要更换 $1 的原因。以下部分提供$1

  • '[^']*' 匹配引号之间的任何内容

  • [^'-] 匹配不是-' 的字符

正则表达式的其余部分捕获-- 和行中的其余字符(请记住,正则表达式一次只应用于一行)。

此方法没有考虑到一些事情。但它比其他方法更强大,所以这些边缘情况不太可能出现:

  • 它仅适用于跨越一行的字符串。
  • 它无法识别字符串中的转义 ' 字符。
  • 它不喜欢在引号外看到一个破折号。

如果您认为上述任何问题与您的问题相关(或者您遇到了其他问题),请随时告诉我,我会查看有关更新此答案的信息。

【讨论】:

    猜你喜欢
    • 2017-12-03
    • 2019-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-05
    • 2018-09-12
    • 2021-11-20
    • 1970-01-01
    相关资源
    最近更新 更多