regex - 用于在一行中搜索、拆分和连接的 Powershell 脚本

标签 regex powershell

星期五我一直在绞尽脑汁地思考处理 Sql Server 对象名称的正则表达式问题。

我的 Powershell 脚本的输入是过程名称。该名称可以采用多种形式,例如

dbo.Procedure
[dbo].Procedure
dbo.[Procedure.Name]

等等

到目前为止,我想出了以下方法将值拆分为其组成部分:

[string[]] $procNameA = $procedure.Split("(?:\.)(?=(?:[^\]]|\[[^\]]*\])*$)")

此外,我有一个正则表达式,可以用来处理方括号

(?:\[)*([A-Za-z0-9. !]+)(?:\])*

这就是我有限的正则表达式经验所能达到的程度。

现在我可以通过处理 ForEach 中的每个元素并在那里进行正则表达式替换来处理很多这样的问题,但你知道这看起来就是这样,我不知道,笨拙。因此,我向任何路过的 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 专家了 - 我该怎么做?

请将任何答案限制为使用我实际可以使用的代码来完全回答问题,而不仅仅是语法建议。

澄清:我敏锐地意识到,有时“缓慢而稳定地赢得比赛”可能适用于此,并且从支持角度来看,在 ForEach 中处理其余部分可能会更安全,但这不是观点。部分原因是为了帮助我了解 RegEx 的灵活性,因此这更多的是一种教育练习,而不是哲学练习。

最佳答案

好吧,这个怎么样:

@'
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 的下一部分与上面的步骤完全相同,但捕获组的名称不同)
  • $ -- 匹配字符串结尾

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

关于regex - 用于在一行中搜索、拆分和连接的 Powershell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44333165/

相关文章:

regex - Powershell函数在文本文件中替换或添加行

powershell - 当调用仅返回一个对象时,如何强制 Powershell 返回一个数组?

python - 将使用以 '$' 结尾的正则表达式进行优化的向后搜索

MySQL RegExp 出现错误 'repetition-operator operand invalid'

调车场算法能否解析POSIX正则表达式?

powershell - 如何使用Powershell将\\server\Share $替换为D:

powershell - 从批处理文件运行PS1文件,拇指驱动器上位于同一文件夹

java - 拆分段落中的每个字符串

regex - 如何比较两个文件之间字段的特定部分

Powershell:为什么我需要转义 $args 中的双破折号参数?