我需要沿着批处理定界符边界拆分T-SQL脚本文件,并分别执行每个段。 拆分很容易。 GO语句必须在一行上单独存在,并且只能在空格之前和之后。 (例外:GO也可以跟在数字后面,但不能是变量。我现在暂时忽略这种情况。现在我也忽略了GO之后插入注释的情况)
但是,可以在块注释内找到GO语句(显然会忽略它们)。沿该边界分割将导致代码损坏。 如果脚本文件在块注释中包含GO语句,我想检查并拒绝它。
到目前为止,我已经构建了此正则表达式:
(\/\*)(.?([^\*][^\/])*?)(^(\s*?)go(\s*?)$)(.?([^\/][^\*])*?)(?=(\*\/))
几乎可以使用,但是仍然存在问题。
拆分和识别不兼容的文件将在PowerShell中完成。
注意:在这个阶段已经建立,我们还不会使用解析器。可能的解析器选项仍在调查中
我通过添加和删除字母在regex101.com中进行了测试:
/*
llaa
GO
*/
GO
/*
a
*/
GO
a
/*
GOaaa
*/
a
GO
/*
a
*/
答案 0 :(得分:1)
请尝试以下正则表达式,如果找到内部注释$true
,则该正则表达式仅应产生GO
;请注意,它还会正确检测到GO
后跟一个(十进制)数字:
@'
/* a comment with GO, but not on its own line */
/* This GO should be found.
GO 12
*/
/* This one is outside a comment */
GO
'@ -match '(?sm)/[*](.(?![*]/))+?^\s*go(\s+\d+)?\s*$'
由于存在嵌入评论的$true
,因此上述内容产生GO 12
。
(?sm)
打开内联选项s
(也使.
匹配\n
)和m
(使^
和{ {1}}也匹配行的开始和结束)。
$
匹配块注释的开头(/[*]
是必须转义的元字符(*
),以便从字面上解释或在字符集中指定({\*
),如此处)。
[...]
匹配单个字符((.(?![*]/))+?
)后面不跟文字.
(使用*/
,负前瞻) ,一次或多次((?!...)
),但非贪婪(+
)。
?
行的关键。 GO
匹配行的开头(^\s*go
),然后是空白的空格(^
),然后是文字\s*
(请注意,PowerShell的go
运算符不区分大小写 )。
-match
可选((\s+\d+)?
)匹配非空白空格(?
),后跟一个或多个(\s+
)数字({{1} })。
+
匹配到行尾的空白行。
假设所有块注释的格式正确,则无需匹配其余注释。
对于不只是拒绝不必要的输入,TheMadTechnician建议使用\d
,它可以有效地 从输入中消除嵌入了\s*$
行的那些块注释:
-split
以上内容将以下内容存储在变量GO
中-请注意,带有嵌入式$sanitized = @'
/* a comment with GO, but not on its own line */
before
/* This GO should be found.
GO 12
*/
after
/* This one is outside a comment */
GO
...
/* Another comment with a GO.
foo
GO
*/
last
'@ -split '(?sm)/[*](?:.(?![*]/))+?^\s*go(?:\s+\d+)?\s*$.+?[*]/' -join ''
语句的块注释已消失:
$sanitized
如果您随后想通过剩余的-未注释的,有效的-GO
语句将生成的脚本分成多个组成部分:
/* a comment with GO, but not on its own line */
before
after
/* This one is outside a comment */
GO
...
last
正如您所指出的,GO
isn't actually a part of T-SQL:
GO
不是Transact-SQL语句;它是$sanitized -split '(?m)^\s*go(?:\s+\d+)?\s*$'
和GO
实用程序以及SQL Server Management Studio代码编辑器所识别的命令
关于您尝试过的事情:
您的sqlcmd
子表达式(此处简化)旨在将块注释的开头与嵌入式osql
匹配,在确保子串/\*(.?([^*][^/])*?)^\s*?go
不是上无效 em>存在;它会同时产生误报和误报。
误报的示例(匹配,但不应该):
GO
否定否定示例(不匹配,但应该匹配):
*/
正如您在评论中所怀疑的那样,问题在于/*a*/
go
与字符的对匹配,因此匹配行为最终取决于输入字符的数量是奇数还是偶数。使用简化的示例:
/*a*
go
只有否定超前断言(如上所示)才能可靠地排除给定的(多字符)字符串。
答案 1 :(得分:0)
我的建议是删除注释,然后拆分代码。