Java Regex находит однострочные комментарии Oracle, за исключением строки - PullRequest
2 голосов
/ 09 декабря 2011

Найти однострочные комментарии Oracle, кроме тех, которые появляются внутри строки.

Например:

-- This is a valid single line comment

Но

'This is a string -- and it is not a comment';

Я использую это регулярное выражениечтобы найти однострочные комментарии

--.*$

, можно обработать несколько случаев, но есть несколько сложных.Вы можете использовать этот скрипт для справки

-- this is a single line comment

CREATE OR REPLACE PROCEDURE "MAIL_WITH_ATTACHMENT" ( ) 
IS    
tmp varchar(2) ; -- this is a comment 
tmp1 varchar(2) := 'some texxt'; -- this is another comment
tmp2 varchar(3) := 'some more --text'; -- this is one more comment
tmp3 varchar(4) := 'this regex isn't --working properly'; -- Don't you think this is another 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; 

Результат должен быть таким

[1] : -- this is a single line comment
[2] : -- this is a comment 
[3] : -- this is another comment
[4] : -- this is one more comment
[5] : -- Don't you think this is another comment

Спасибо

Ответы [ 3 ]

4 голосов
/ 12 декабря 2011

Лично я бы использовал анализатор 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
1 голос
/ 09 декабря 2011

Это регулярное выражение должно работать нормально:

Pattern p = Pattern.compile("^[^']*('[^']*'[^']*)*(--.*)$");

за исключением случая [5]. Но прежде чем начать слишком усложнять регулярное выражение, вы уверены, что Oracle не жалуется на эту строку?

EDIT

Это код, который я использовал для проверки регулярных выражений

String[] text =
    {
        "-- this is a single line comment",
        "",
        "CREATE OR REPLACE PROCEDURE \"MAIL_WITH_ATTACHMENT\" ( ) ",
        "IS    ",
        "tmp varchar(2) ; -- this is a comment ",
        "tmp1 varchar(2) := 'some texxt'; -- this is another comment",
        "tmp2 varchar(3) := 'some more --text'; 'blah --blah' -- this is one more comment",
        "tmp3 varchar(4) := 'this regex isn't --working properly'; -- Don't you think this is another 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 p = Pattern.compile("^[^']*('[^']*'[^']*)*(--.*)$");
Matcher m = p.matcher("");

for (String s : text) {
  m.reset(s);
  if (m.find()) {
    System.out.println(m.group(m.groupCount()));
  }
}

А вот и вывод:

-- this is a single line comment
-- this is a comment 
-- this is another comment
-- this is one more comment
--working properly'; -- Don't you think this is another comment

Как видите, последняя строка вывода "неправильная". Но, как вы сказали, Oracle тоже не любит такую ​​строку. После того, как вы исправите isn't в isn''t, выходной сигнал также будет правильным.

1 голос
/ 09 декабря 2011

Это должно помочь.Если вы читаете построчно;

   str = str.replaceAll("'{1}.*'{1}", "").replaceFirst(".*--", "--");

Введите: -sd '--asdsa --- asdsadasdsad' ||'asdsad' ||'asdsadasd' - здесь x что-то

Вывод: - здесь x что-то

Редактировать: Окончательная версия после 3 редактирования:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...