Разделенная строка в RegEx с разделителем (точка с запятой;), кроме тех, которые появляются внутри строки - PullRequest
2 голосов
/ 15 сентября 2011

У меня есть строка Java, которая на самом деле является сценарием SQL.

CREATE OR REPLACE PROCEDURE Proc
   AS
        b NUMBER:=3;
        c VARCHAR2(2000);
    begin
        c := 'BEGIN ' || ' :1 := :1 + :2; ' || 'END;';
   end Proc;

Я хочу разбить скрипт на точки с запятой, кроме тех, которые появляются внутри строки. Желаемый результат - четыре разных строки, как указано ниже

1- CREATE OR REPLACE PROCEDURE Proc AS b NUMBER:=3
2- c VARCHAR2(2000)
3- begin c := 'BEGIN ' || ' :1 := :1 + :2; ' || 'END;';
4- end Proc

Метод Java Split () также разбивает вышеуказанную строку на токены. Я хочу сохранить эту строку такой, какая она есть, так как точки с запятой находятся внутри кавычек.

c := 'BEGIN ' || ' :1 := :1 + :2; ' || 'END;';

Вывод метода Java Split ()

1- c := 'BEGIN ' || ' :1 := :1 + :2
2- ' || 'END
3- '

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

===================== CASE-2 ==================== ====

Над разделом ответили и его работа

Вот еще один более сложный случай

============================================ ==========

У меня есть SQL-скрипт, и я хочу маркировать каждый SQL-запрос. Каждый запрос SQL отделяется точкой с запятой (;) или косой чертой (/).

1- Я хочу экранировать точку с запятой или знак /, если они появляются внутри строки, такой как

...WHERE col1 = 'some ; name/' ..

2- Выражение также должно избегать любого синтаксиса многострочного комментария, который / *

Вот ввод

/*Query 1*/
SELECT
*
FROM  tab t
WHERE (t.col1 in (1, 3)
            and t.col2 IN (1,5,8,9,10,11,20,21,
                                     22,23,24,/*Reaffirmed*/
                                     25,26,27,28,29,30,
                                     35,/*carnival*/
                                     75,76,77,78,79,
                                     80,81,82, /*Damark accounts*/
                                     84,85,87,88,90))
;
/*Query 2*/    
select * from table
/
/*Query 3*/
select col form tab2
;
/*Query 4*/
select col2 from tab3 /*this is a multi line comment*/
/

Желаемый результат

[1]: /*Query 1*/
    SELECT
    *
    FROM  tab t
    WHERE (t.col1 in (1, 3)
                and t.col2 IN (1,5,8,9,10,11,20,21,
                                         22,23,24,/*Reaffirmed*/
                                         25,26,27,28,29,30,
                                         35,/*carnival*/
                                         75,76,77,78,79,
                                         80,81,82, /*Damark accounts*/
                                         84,85,87,88,90))

[2]:/*Query 2*/    
    select * from table

[3]: /*Query 3*/
    select col form tab2

[4]:/*Query 4*/
    select col2 from tab3 /*this is a multi line comment*/

Половина этого уже может быть достигнута с помощью того, что было предложено мне в предыдущем посте (ссылка на начало), но когда в запросы вводится синтаксис комментариев (/ *), и каждый запрос также может быть разделен косой чертой (/ ), выражение не работает.

Ответы [ 3 ]

4 голосов
/ 15 сентября 2011

Шаблон регулярного выражения ((?:(?:'[^']*')|[^;])*); должен дать вам то, что вам нужно.Используйте цикл while и Matcher.find() для извлечения всех операторов SQL.Что-то вроде:

Pattern p = Pattern.compile("((?:(?:'[^']*')|[^;])*);";);
Matcher m = p.matcher(s);
int cnt = 0;
while (m.find()) {
    System.out.println(++cnt + ": " + m.group(1));
}

Используя предоставленный вами пример SQL, вы получите:

1: CREATE OR REPLACE PROCEDURE Proc
   AS
        b NUMBER:=3
2: 
        c VARCHAR2(2000)
3: 
    begin
        c := 'BEGIN ' || ' :1 := :1 + :2; ' || 'END;'
4: 
   end Proc

Если вы хотите получить завершающий ;, используйте m.group(0) вместо m.group(1).

Для получения дополнительной информации о регулярных выражениях см. Pattern JavaDoc и эту замечательную ссылку .Вот краткий обзор картины:

(              Start capturing group
  (?:          Start non-capturing group
    (?:        Start non-capturing group
      '        Match the literal character '
      [^']     Match a single character that is not '
      *        Greedily match the previous atom zero or more times
      '        Match the literal character '
    )          End non-capturing group
    |          Match either the previous or the next atom
    [^;]       Match a single character that is not ;
  )            End non-capturing group
  *            Greedily match the previous atom zero or more times
)              End capturing group
;              Match the literal character ;
0 голосов
/ 19 мая 2013

У меня была такая же проблема. Я видел предыдущие рекомендации и решил улучшить обработку для:

  • Комментарии
  • Избежавшие одинарные кавычки
  • Одиночные запросы не заканчиваются точкой с запятой

Мое решение написано для Java. Некоторые вещи, такие как обратная косая черта и режим DOTALL, могут меняться с одного языка на другой.

это сработало для меня "(?s)\s*((?:'(?:\\.|[^\\']|''|)<em>'|/\</em>.*?\*/|(?:--|#)[^\r\n]<em>|[^\\'])</em>?)(?:;|$)"

"
(?s)                 DOTALL mode. Means the dot includes \r\n
\\s*                 Initial whitespace
(
    (?:              Grouping content of a valid query
        '            Open string literal
        (?:          Grouping content of a string literal expression
            \\\\.    Any escaped character. Doesn't matter if it's a single quote
        |
            [^\\\\'] Any character which isn't escaped. Escaping is covered above.
        |
            ''       Escaped single quote
        )            Any of these regexps are valid in a string literal.
        *            The string can be empty 
        '            Close string literal
    |
        /\\*         C-style comment start
        .*?          Any characters, but as few as possible (doesn't include */)
        \\*/         C-style comment end
    |
        (?:--|#)     SQL comment start
        [^\r\n]*     One line comment which ends with a newline
    |
        [^\\\\']     Anything which doesn't have to do with a string literal
    )                Theses four tokens basically define the contents of a query
    *?               Avoid greediness of above tokens to match the end of a query
)
(?:;|$)              After a series of query tokens, find ; or EOT
"

Что касается вашего второго случая, обратите внимание, что последняя часть регулярного выражения выражает то, как закончится ваше регулярное выражение. Сейчас он принимает только точку с запятой или конец текста . Тем не менее, вы можете добавить все, что вы хотите в концовку. Например, (?:;|@|/|$) принимает при и косая черта в качестве конечных символов. Я не проверял это решение для вас, но не должно быть трудным.

0 голосов
/ 15 сентября 2011

То, что вы можете попробовать, это просто разделить на ";". Затем для каждой строки, если она имеет нечетное число символов «s», объедините ее со следующей строкой, пока в ней не будет четного числа, добавляющих символы «;».

...