Java正则表达式:从字符串中删除SQL注释

3
希望有人可以帮我解决这个问题!
我有一个看起来像这样的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()函数基本上做它所说的事情。 现在我想构建一个正则表达式来从字符串中删除块注释。文件中只有块注释/* */,没有--

我目前尝试过的:

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

很遗憾,我不是很擅长正则表达式...

我遇到了所有与“匹配的字符串看起来像/*注释*/真实语句/*另一个注释*/”等相似的问题...


你的正则表达式需要使用惰性运算符 ? - Gabber
4个回答

10

试试看

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

(注意这里使用了?,代表“懒惰模式”)。

编辑:如果需要匹配多行注释,请使用以下方法:

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

希望这对你有用。


它似乎适用于单行块注释,但不适用于跨越多行的块注释!! .*? 是否也匹配回车符? - Eric C.
哎呀,你需要使用一个带有 Pattern.DOTALL 标志的完整的 Pattern 实例。我会很快修改答案。 - Alexander Pavlov
阅读了Pattern类的文档之后,它可以正常工作了,非常感谢!! - Eric C.

2
尝试以下方法:
String s = "/* comment */ select * from XYZ; /* comment */";
System.out.println(s.replaceAll("/\\*.*?\\*/", ""));

输出:

 select * from XYZ; 

".*?" 代表使用 懒惰而不是贪婪(这意味着 ".*" 默认情况下匹配尽可能长的字符串,即贪婪匹配 => 您必须在 ".*?" 表达式中使用 "?" 来配置为非贪婪匹配)。"

感谢您对惰性和贪婪的解释。我至少学到了一些东西。但请看看我在Alexander Pavlov帖子上的评论。 - Eric C.

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("/\\*.*?\\*/", ""));
    }
}

1

它不会百分之百地工作。

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

我正在研究一种解决方案......似乎很复杂。

到目前为止,我有:

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

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


好的,现在字符串中的注释不再是问题了,但对于多行注释之前的单行注释...我认为使用解析器会更容易:(?:[^']*?|'(?:[^']|'')*?'(?!'))*?\K\/\*.*?\*\/ - user2433984

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接