用于搜索,拆分和连接的Powershell脚本

时间:2017-06-02 16:05:28

标签: regex powershell

在处理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的灵活性,因此这更像是一种教育活动,而不是一种哲学活动。

1 个答案:

答案 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的命名捕获组
      • [^\]]+ - 匹配字面右方括号]
      • 的任何字符中的1个或多个字符
    • ) - 结束schema捕获组
    • | - 轮换;如果前一个表达式不匹配,请尝试此后的内容
    • (?<schema> - 再次启动一个名为schema的命名捕获组;只有在另一个人没有匹配的情况下才会尝试。
      • [^\.]+ - 匹配字面点.
      • 的任何字符中的1个或多个字符
    • ) - 结束备用schema捕获组
  • ) - 结束非捕获组
  • \. - 匹配文字点.(这是分隔架构和proc的一个)
    • proc的下一部分与上面的步骤完全相同,但捕获组的名称不同)
  • $ - 匹配字符串的结尾

在替换中,我们只使用${name}语法而不是数字$1来限定组的名称(这实际上也会起作用)。