【问题标题】:Java regex to remove SQL comments from a stringJava 正则表达式从字符串中删除 SQL 注释
【发布时间】:2012-04-19 10:11:12
【问题描述】:

希望有人能帮我解决这个问题!

我有一个如下所示的 sql 文件:

CREATE TABLE IF NOT EXISTS users(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    firstname VARCHAR(30) NOT NULL,
    lastname VARCHAR(30) NOT NULL,

    PRIMARY KEY (id),
    CONSTRAINT UNIQUE (firstname,lastname)
)
ENGINE=InnoDB
;

INSERT IGNORE INTO users (firstname,lastname) VALUES ('x','y');
/*
INSERT IGNORE INTO users (firstname,lastname) VALUES ('a','b');
*/

我已经建立了一个 web 应用程序,它在启动时使用这个函数初始化一个 mysql 数据库:

public static void initDatabase(ConnectionPool pool, File sqlFile){
    Connection con = null;
    Statement st = null;
    String mySb=null;
    try{
        con = pool.getConnection();
        mySb=IOUtils.copyToString(sqlFile);

        // We use ";" as a delimiter for each request then we are sure to have well formed statements
        String[] inst = mySb.split(";");

        st = con.createStatement();

        for(int i = 0; i<inst.length; i++){
            // we ensure that there is no spaces before or after the request string
            // in order not to execute empty statements
            if(!inst[i].trim().isEmpty()){
                st.executeUpdate(inst[i]);
            }
        }
        st.close();
    }catch(IOException e){
        throw new RuntimeException(e);
    }catch(SQLException e){
        throw new RuntimeException(e);
    }finally{
        SQLUtils.safeClose(st);
        pool.close(con);
    }
}

(这个功能是在网上找到的。作者,请原谅我没有引用你的名字,我丢了!!)

只要没有 SQL 注释块,它就可以完美运行。

copyToString() 函数基本上按照它说的做。 我现在想要的是构建一个正则表达式,它将从字符串中删除块 cmets。我在文件中只有块 cmets /* */,没有 --

到目前为止我所尝试的:

mySb = mySb.replaceAll("/\\*.*\\*/", "");

不幸的是,我不太擅长正则表达式...

我遇到了“匹配的字符串看起来像/* comment */ real statement /* another comment*/”等等的所有麻烦......

【问题讨论】:

  • 你的正则表达式中需要惰性运算符?

标签: java sql regex


【解决方案1】:

试试

mySb = mySb.replaceAll("/\\*.*?\\*/", "");

(注意? 代表“lazy”)。

编辑:要覆盖多行 cmets,请使用以下方法:

Pattern commentPattern = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL);
mySb = commentPattern.matcher(mySb).replaceAll("");

希望这对你有用。

【讨论】:

  • 它似乎适用于单行的块注释,但不适用于多行的块! .*? 是否也匹配回车符?
  • 哎呀,您需要使用带有Pattern.DOTALL 标志的完整Pattern 实例。我会尽快修改答案。
  • 在阅读了Pattern 类的文档后,它可以工作了,非常感谢!!
【解决方案2】:

你需要像这样使用不情愿的限定词:

public class Main {

    public static void main(String[] args) {
        String s = "The matched string look something like /* comment */ real statement /* another comment*/";
        System.err.println(s.replaceAll("/\\*.*?\\*/", ""));
    }
}

【讨论】:

    【解决方案3】:

    尝试以下方法:

    String s = "/* comment */ select * from XYZ; /* comment */";
    System.out.println(s.replaceAll("/\\*.*?\\*/", ""));
    

    输出:

     select * from XYZ; 
    

    .*? 代表使用 Laziness Instead of Greediness(这意味着 .* 默认匹配最大的字符串,即贪婪 => 您必须使用 ? 将其配置为非贪婪.*? 表达式)。

    【讨论】:

    • 感谢懒惰和贪婪的解释。我至少学到了一些东西。但请参阅我对 Alexander Pavlov 帖子​​的评论。
    【解决方案4】:

    它不会 100% 起作用

    cmets 可以是 SQL 中指定的有效字符串的一部分,在这种情况下,它们需要保留...

    我只是在研究一个解决方案……似乎很复杂

    目前为止:

    \G(?:[^']*?|'(?:[^']|'')*?'(?!'))*?\/\*.*?\*\/
    

    但它匹配所有内容,而我只需要匹配注释......并且刚刚发现它可能会在前面有单行注释时失败......该死的

    【讨论】:

    • 好的,所以现在字符串中的 cmets 将不再是问题,但是对于多行 cmets 之前的单行 cmets...我认为解析器真的会更容易:(?:[^']*?|'(?:[^']|'')*?'(?!'))*?\K\/\*.*?\*\/
    猜你喜欢
    • 2012-03-30
    • 2012-04-08
    • 2011-04-01
    • 2021-01-17
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-28
    • 2021-09-07
    相关资源
    最近更新 更多