【问题标题】:Powershell force 5 digit format in a string patternPowershell 以字符串模式强制使用 5 位数字格式
【发布时间】:2017-11-09 01:19:59
【问题描述】:

所以我现在(如下)将搜索XX-##-# 并将其强制为XX-##-#0000

我怎样才能返回XX-##-0000#

有没有办法强制最后 5 位数字填充前面的 0,以覆盖其他可能性(XX-##-##XX-##-###XX-##-####)?与复制 4 次相反,每次稍作调整。

$Pattern1 = '[a-zA-Z][a-zA-Z]-[0-9][0-9]-[0-9]'
Get-ChildItem 'C:\path\to\file\*.txt' -Recurse | ForEach {
     (Get-Content $_ | 
     ForEach  { $_ -replace $Pattern1, ('$1'+'0000')}) | 
     Set-Content $_
}

谢谢。

编辑:我想做以下事情

Search           Replacement
XX-##-#          XX-##-0000#
XX-##-##         XX-##-000##
XX-##-###        XX-##-00###
XX-##-####       XX-##-0####

【问题讨论】:

  • $Pattern1$date_Pattern1?您的 $Pattern1 不包含捕获组,您使用 $1 引用了一些组 - 请显示您的所有代码。
  • @WiktorStribiżew 我的错,它应该是 $Pattern1,我修好了.. $1 是一个反向引用
  • 是的,对捕获组值的反向引用。您的正则表达式没有捕获组。
  • @WiktorStribiżew 哦..我必须跳入工作中的其他事情,但我想我明白我现在缺少什么..我会再试一次..谢谢
  • 我可能太忙了,这里是an approach you may pursue

标签: regex powershell text return-value


【解决方案1】:

不幸的是,PowerShell 的 -replace 运算符不支持将 表达式(脚本块)作为替换字符串传递,此处需要简洁的解决方案。

不过,你可以使用the appropriate [regex] .NET type's .Replace() method overload:

注意:此解决方案仅关注基于正则表达式的替换部分,但很容易将其嵌入问题的更大管道中。

# Define sample array.
$lines = @'
Line 1 AB-00-0 and also AB-01-1
Line 2 CD-02-22 after
Line 3 EF-03-333 it
Line 4 GH-04-4444 goes 
Line 5 IJ-05-55555 on
'@ -split "`n"

# Loop over lines...
$lines | ForEach-Object {
  # ... and use a regex with 2 capture groups to capture the substrings of interest
  #     and use a script block to piece them together with number padding
  #     applied to the 2nd group
  ([regex] '\b([a-zA-Z]{2}-[0-9]{2}-)([0-9]+)').Replace($_, { 
    param($match)
    $match.Groups[1].Value + '{0:D5}' -f [int] $match.Groups[2].Value
  })
}

以上产出:

Line 1 AB-00-00000 and also AB-01-00001
Line 2 CD-02-00022 after
Line 3 EF-03-00333 it
Line 4 GH-04-04444 goes 
Line 5 IJ-05-55555 on

【讨论】:

    【解决方案2】:

    这是可以帮助您解决当前问题的辅助信息 代码并得出正确的结论。

    https://technet.microsoft.com/en-us/library/ee692795.aspx

    我建议结合使用本文档中列出的技术。提供的示例对数字格式非常有帮助:

    $a = 348 
    "{0:N2}" -f $a
    "{0:D8}" -f $a
    "{0:C2}" -f $a
    "{0:P0}" -f $a
    "{0:X0}" -f $a
    
    Output
    348.00
    00000348
    $348.00
    34,800 %
    15C
    

    您还可以使用 [String]::Format 并添加一些断言以确保项目的格式正确;例如,如果未指定特定值,您可以简单地将其默认为 0。

    https://blogs.technet.microsoft.com/heyscriptingguy/2013/03/11/understanding-powershell-and-basic-string-formatting/

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      创建捕获组。在将格式应用于第二个时将它们组合起来。

      编辑:更新以删除该行仅是匹配字符串的假设。注意,每行只有一个匹配的假设仍然存在。

      $Pattern1 = '^(.*?)([a-zA-Z][a-zA-Z]-\d\d-)(\d+)(.*)$'
      Get-ChildItem 'C:\path\to\file\*.txt' -Recurse |
          ForEach-Object {
              (Get-Content $_ | 
                  ForEach-Object {
                      if ($_ -match $Pattern1) {
                           "{0}{1}{2:D5}{3}" -f $matches[1],$matches[2],[int]$matches[3],$matches[4]
                      } else {
                          $_
                      }
                  }) | Set-Content -Path $_
          }
      

      【讨论】:

        【解决方案4】:
        #example of the text we'd load in from file / whereever
        $value = @'
        this is an example of a value to be replaced: 1AB-23-45 though
        we may also want to replace 0CD-87-6 or even 9ZX-00-12345 that
        '@
        
        #regex to detect the #XX-##-##### pattern you mentioned (\b word boundaries included so we don't pick up these patterns if they're somehow part of a larger string; though that seems unlikely in this case) 
        $pattern = '\b(\d[A-Z][A-Z])-(\d\d)-(\d{1,5})\b'
        #what we want our output to look like; with placeholders 0, 1, & 2 taking values from our captures from the above.
        $format = '{0}-{1}-{2:D5}'
        
        <#
         # #use select-string to allow us to capture every match, rather than just the first
         # $value | Select-String -Pattern $pattern -AllMatches | %{
         #     #loop through every match replacing the matched string with the reformatted version of itself
         #     $_.matches | %{
         #         #NB: we have to convert the match in group#3 to int to ensure the {2:D3} formatting from above will be applied as expected
         #         $value = $value -replace "\b$($_.value)\b", ($format -f $_.Groups[1].Value,$_.Groups[2].Value,([int]$_.Groups[3].Value))
         #     }
         # }
        #>
        
        #or this version's a little more efficient; using the matched positions to replace the strings in those positions with our new formatted value
        $value | Select-String -Pattern $pattern -AllMatches | %{
            $_.matches | sort index -Descending | %{
                $value = $value.remove($_.index, $_.value.length).insert($_.index, ($format -f $_.Groups[1].Value,$_.Groups[2].Value,([int]$_.Groups[3].Value)))
            }
        }
        
        
        $value
        

        【讨论】:

          【解决方案5】:

          使用前瞻:

          $Pattern1 = '(?<=[a-zA-Z][a-zA-Z]-\d\d-)(?=\d)(?!\d\d)'
          Get-ChildItem 'C:\path\to\file\*.txt' -Recurse | ForEach {
          (Get-Content $_ | 
          ForEach  { $_ -replace $date_pattern1, ('000')}) | 
          Set-Content $_
          

          前瞻(?=\d) 断言下一个字符是数字,而不消耗。

          负前瞻 '(!\d\d) 断言末尾没有 2 位数字,因此您不会以 XX-##-0000## 结尾。

          还要注意\d(一个“数字”)与[0-9] 完全相同(但更容易编码。

          我认为你必须更换 4 次。

          【讨论】:

          • 谢谢..我不清楚我想做什么..请查看编辑
          • \d is not exactly the same as [0-9] in .NET regex. 此外,我怀疑'$1'+'0000' 是否会起作用。
          • @WiktorStribiżew 仅供参考,它没有用.. 输入仍然感谢@Bohemian
          • @physlexic 立即尝试
          【解决方案6】:

          简单的例子。搜索字符串末尾的数字。

          $text = 'aa-11-123'
          $text -match '\d+$'  # sets $matches
          $result = ($matches.0).padleft(5,'0')
          $text -replace '\d+$', $result  # \d* won't work right
          
          aa-11-00123
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-07-21
            • 1970-01-01
            • 2022-03-30
            • 2013-08-13
            • 1970-01-01
            相关资源
            最近更新 更多