Powershell以字符串模式强制使用5位数字格式

时间:2017-06-07 15:25:56

标签: regex powershell text return-value

所以我现在(将在下面)将搜索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####

6 个答案:

答案 0 :(得分:4)

不幸的是,PowerShell的GET https://sheets.googleapis.com/v4/spreadsheets/spreadsheetId/values/Sheet1!A1:D5 运算符不支持传递表达式(脚本块)作为替换字符串,这是一个简洁的解决方案。

但是,您可以使用the appropriate [regex] .NET type's .Replace() method overload

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

-replace

以上产量:

# 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
  })
}

答案 1 :(得分:3)

  

这是辅助信息,可以帮助您修复当前   代码并得出正确的结论。

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/

希望这会有所帮助。

答案 2 :(得分:1)

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

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

$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 $_
    }

答案 3 :(得分:0)

使用前瞻:

$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(&#34;数字&#34;)与[0-9]完全相同(但更容易编码。

我认为你必须做4次替换。

答案 4 :(得分:0)

#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 :(得分:0)

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

$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