在处理Sql Server对象名称时遇到了正则表达式问题。
我的Powershell脚本的输入是过程名称。名称可以采用多种形式,例如
dbo.Procedure
[dbo].Procedure
dbo.[Procedure.Name]
等
到目前为止,我想出了以下内容,将价值分成了它的组成部分:
[string[]] $procNameA = $procedure.Split("(?:\.)(?=(?:[^\]]|\[[^\]]*\])*$)")
另外,我有一个可以用来处理方括号的正则表达式
(?:\[)*([A-Za-z0-9. !]+)(?:\])*
这就是我有限的正则表达式经验所带来的。
现在我可以通过处理 ForEach 中的每个元素并在那里进行RegEx替换来解决很多问题,但是我知道这似乎是这样,我不知道,笨拙。所以,我对任何过往的Powershell& RegEx大师:"如何在一行中完成所有这些?"
我正在寻找的是我可以获得以下结果的地方
Original Corrected
===================== =====================
dbo.ProcName [dbo].[ProcName]
dbo.[ProcName] [dbo].[ProcName]
[dbo].ProcName [dbo].[ProcName]
[dbo].[ProcName] [dbo].[ProcName]
[My.Schema].[My.Proc] [My.Schema].[My.Proc]
[My.Schema].ProcName [MySchema].[ProcName]
dbo.[ABadBADName! [dbo].[[ABadBADName!]
(注意对象名称以开头但不结束的最后一个实例带有方括号(不是我期待那个[并且如果我看到我团队中的任何人命名一个对象]就像我要问人力资源是否可以解雇它一样],但我确实希望如此彻底)。
认为涵盖了一切......
所以,对你来说,Powershell& RegEx大师 - 我该怎么做?
请使用我实际可以使用的代码来限制任何完全回答问题的答案,而不仅仅是语法建议。
澄清:我敏锐地意识到,有时候“缓慢而稳定地赢得比赛”#39;可以在这里申请并且支持明智地处理ForEach中的其余部分可能更安全,但这不是重点。部分原因是为了帮助我理解RegEx的灵活性,因此这更像是一种教育活动,而不是一种哲学活动。
答案 0 :(得分:2)
好的,这个:
@'
dbo.ProcName
dbo.[ProcName]
[dbo].ProcName
[dbo].[ProcName]
[My.Schema].[My.Proc]
[My.Schema].ProcName
dbo.[ABadBADName!
'@ -split '\s*\r?\n\s*' | % {
$_ -replace '^(?:\[(?<schema>[^\]]+)\]|(?<schema>[^\.]+))\.(?:\[(?<proc>[^\]]+)\]|(?<proc>[^\.]+))$', '[${schema}].[${proc}]'
}
请注意,我只是在这里使用ForEach-Object
(%
)来迭代您的测试用例;实际替换是使用单个正则表达式/替换完成的。
所以这里的重要部分是正则表达式:
^(?:\[(?<schema>[^\]]+)\]|(?<schema>[^\.]+))\.(?:\[(?<proc>[^\]]+)\]|(?<proc>[^\.]+))$
打破它:
^
- 匹配字符串的开头(?:
- 打开一个非捕获组(用于交替目的)
\[
- 匹配文字左括号[
(?<schema>
- 启动一个名为schema
的命名捕获组
[^\]]+
- 匹配不字面右方括号]
)
- 结束schema
捕获组|
- 轮换;如果前一个表达式不匹配,请尝试此后的内容(?<schema>
- 再次启动一个名为schema的命名捕获组;只有在另一个人没有匹配的情况下才会尝试。
[^\.]+
- 匹配不字面点.
)
- 结束备用schema
捕获组)
- 结束非捕获组\.
- 匹配文字点.
(这是分隔架构和proc的一个)
proc
的下一部分与上面的步骤完全相同,但捕获组的名称不同)$
- 匹配字符串的结尾在替换中,我们只使用${name}
语法而不是数字$1
来限定组的名称(这实际上也会起作用)。