Лично я бы использовал анализатор SQL, чтобы убрать эти комментарии.Проблема с регулярным выражением в том, что он на самом деле не знает своего окружения: регулярному выражению трудно понять, находится ли одиночная кавычка внутри комментария или если --
находится внутри строкового литерала.
Вы можете обойти это, используя регулярное выражение, совпадающее с начала строки и совпадающее со строковыми литералами.Заставить его вести себя как лексический анализатор (первая стадия синтаксического анализа).
Такое регулярное выражение может выглядеть так:
(?m)^((?:(?!--|').|'(?:''|[^'])*')*)--.*$
Быстрый отказ от регулярного выражения:
(?m) # enable multi-line mode
^ # match the start of the line
( # start match group 1
(?: # start non-capturing group 1
(?!--|'). # if there's no '--' or single quote ahead, match any char (except a line break)
| # OR
'(?:''|[^'])*' # match a string literal
)* # end non-capturing group 1 and repeat it zero or more times
) # end match group 1
--.*$ # match a comment all the way to the end of the line
На простом английском языке, который читался бы следующим образом: с каждого начала строки пытайтесь найти ноль или более:
- строковые литералы (
'(?:''|[^'])*'
); - или любой символ, если это не одиночная кавычка, символ разрыва строки или
-
, являющийся частью комментария ((?!--|').
).
и сохраните это совпадение в группе1. Затем сопоставьте комментарий (--.*$
).
Так что теперь все, что вам нужно сделать, это заменить этот шаблон тем, что соответствует в группе 1. Демонстрация:
String sql = "-- this is a single line comment\n" +
"\n" +
"CREATE OR REPLACE PROCEDURE \"MAIL_WITH_ATTACHMENT\" ( ) \n" +
"IS \n" +
"tmp varchar(2) ; -- this is a comment \n" +
"tmp1 varchar(2) := 'some texxt'; -- this is another comment\n" +
"tmp2 varchar(3) := 'some more --text'; -- this is one more comment\n" +
"tmp3 varchar(4) := 'this regex isn''t --working properly'; -- Don't you think this is another comment\n" +
"BEGIN\n" +
"\n" +
" '--This is a Mime message, which your current mail reader may not' || crlf ||\n" +
" ' some more -- characters in a string';\n" +
"\n" +
" mesg:= crlf ||\n" +
" '--This is a Mime message, which your current mail reader may not' || crlf ||\n" +
" ' some more -- characters in a string';\n" +
"END; ";
String stripped = sql.replaceAll("(?m)^((?:(?!--|').|'(?:''|[^'])*')*)--.*$", "$1[REMOVED COMMENT]");
System.out.println(stripped);
, котораянапечатает:
[REMOVED COMMENT]
CREATE OR REPLACE PROCEDURE "MAIL_WITH_ATTACHMENT" ( )
IS
tmp varchar(2) ; [REMOVED COMMENT]
tmp1 varchar(2) := 'some texxt'; [REMOVED COMMENT]
tmp2 varchar(3) := 'some more --text'; [REMOVED COMMENT]
tmp3 varchar(4) := 'this regex isn''t --working properly'; [REMOVED COMMENT]
BEGIN
'--This is a Mime message, which your current mail reader may not' || crlf ||
' some more -- characters in a string';
mesg:= crlf ||
'--This is a Mime message, which your current mail reader may not' || crlf ||
' some more -- characters in a string';
END;
РЕДАКТИРОВАТЬ
И если вы хотите только извлечь комментарии, оберните группу захвата вокруг --.*$
и используйте Pattern
& Matcher
до find()
совпадения:
Matcher m = Pattern.compile("(?m)^(?:(?!--|').|'(?:''|[^'])*')*(--.*)$").matcher(sql);
while(m.find()) {
System.out.println(m.group(1));
}
, которые будут печатать:
-- this is a single line comment
-- this is a comment
-- this is another comment
-- this is one more comment
-- Don't you think this is another comment