Java 正则表达式在delimeter(分号;)上拆分字符串,但出现在字符串内部的字符串除外
我有一个Java字符串,它实际上是一个SQL脚本Java 正则表达式在delimeter(分号;)上拆分字符串,但出现在字符串内部的字符串除外,java,regex,string,stringtokenizer,Java,Regex,String,Stringtokenizer,我有一个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
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- '
请建议一个正则表达式,它可以在分号上拆分字符串,但字符串内部的除外
===========================================================================================
以上部分已得到回答,其工作原理也已完成
这是另一个更复杂的情况
============================================================================
我有一个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*/
上一篇文章(link a start)中向我提出的建议已经实现了一半,但当在查询中引入注释语法(/*),并且每个查询也可以用正斜杠(/)分隔时,表达式就不起作用了。您可能尝试的只是在“;”上拆分。然后,对于每个字符串,如果它有奇数个“s”,则将其与以下字符串连接,直到它有偶数个“s”将“;”s添加回。正则表达式模式
((?:(?:“[^']*”)|[^;])代码>应该能满足您的需要。使用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)
有关正则表达式的更多信息,请参阅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 ;
我也有同样的问题。我看到了以前的建议,并决定改进以下方面的处理:
- 评论
- 转义单引号
- 单个查询不以分号结尾
我的解决方案是为java编写的。反斜杠ECAP和DOTALL模式可能会从一种语言更改为另一种语言
这对我很有效。“(?:”(?:“(?:\.[^\\\\\\].'''.''.''.'.''.''.'.'./\.*.*.*/.[^\r\n].[^\\\\\\'])(?:;[^\\\\\'.$)”
至于第二种情况,请注意regexp的最后一部分表达了正则表达式的结束方式。现在它只接受分号或文本结尾。但是,您可以在结尾添加任何内容。例如,(?:;|@|/|$)
接受at和斜杠作为结束字符。还没有为您测试过此解决方案,但应该不难。对字符串文本中出现的引号进行转义的规则是什么?整个脚本都是从文件中读取并存储在字符串中。有趣的是,有一个相关的问题(#2)实际上与您的问题几乎完全相同。。。请看这里:有人可以研究一下这个场景,并将字符串标记化;和/和转义,如果它们出现在字符串或单个或块注释(/*或--)中。示例:code
sel*from选项卡;SFASDFT这是我已经做过的,但我试图找到一些简单的东西。感谢您的建议上述策略因以下声明而失败。但可以通过查看转义字符选择“hello\”来修复此问题;世界",;你能稍微解释一下这个模式吗,因为我很难理解它。(?:“[^']*”)=非捕获组匹配起始引号到结束引号[^;]=不是分号的单个字符(?:(?:“[^']*”)|[^;]*=匹配所有不包含在引号中的第一个分号的非捕获组((?:(?:“[^']*”)|[^;])*);=捕获第一个分号之前的所有内容,包括不在引号中的分号
"
(?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
"