在 Powershell 中使用正则表达式时 Leftpad 不起作用

Leftpad doesn't work when using with regex in Powershell

这里有两个代码块,显示了 Leftpad 的奇怪行为。

$array = "z", "fg"
$array -replace "(\w{1,2})", ''.PadLeft(2, "0")
# output: z, fg

$array = "z", "fg"
$array -replace "(\w{1,2})", ''.PadLeft(3, "0")
# output: 0z, 0fg

pad长度怎么不固定?

编辑:@LotPings

我问这个另一个问题是因为您在应用于 rename-item 语句时这样做的方式不会影响名称中带有括号的文件。

$file_names = ls "G:\Donwloads\Srt Downloads" -Filter *.txt
# the files are: "Data Types _ C# _ Tutorial 5.txt", "If Statements (con't) _ C# _ Tutorial 15.txt"
$file_names | 
    ForEach{
        if ($_.basename -match '^([^_]+)_[^\d]+(\d{1,2})$')
            { 
            $file_names | 
                Rename-Item -NewName `
                    { ($_.BaseName -replace $matches[0], ("{0:D2}. {1}" -f [int]$matches[2],$matches[1])) + $_.Extension }
            } 
           }

# output: 05. Data Types.txt
#         If Statements (con't) _ C# _ Tutorial 15.txt

至于.PadLeft,我以为正则表达式替换组是字符串类型的,它应该与.PadLeft一起使用,但它没有。

你的最后一个问题应该表明你对行动顺序的假设是错误的。
又一次证明你错了。

to your 提供了一个替代方案,也适用于此:

("Data Types _ C# _ Tutorial 5", "If Statements (con't) _ C# _ Tutorial 15") |
  ForEach{ 
    if ($_ -match '^([^_]+)_[^\d]+(\d{1,2})$'){
      "{0:D2}. {1}" -f [int]$matches[2],$matches[1]
    } 
  }

示例输出:

05. Data Types
15. If Statements (con't)

您问题的最后一次编辑实际上是一个新问题...

  • Rename-Item 接受管道输入,因此在使用
  • 时不需要 ForEach-Object
  • Where-Object 用 -match 运算符替换 if.
    $Matches 集合以相同的方式提供。
  • 我真的不知道你为什么在使用 -format 运算符从头构建 NewName 时坚持使用 -replace 运算符。

$file_names = Get-ChildItem "G:\Donwloads\Srt Downloads" -Filter *.txt

$file_names | Where-Object BaseName -match '^([^_]+)_[^\d]+(\d{1,2})$' |
    Rename-Item -NewName {"{0:D2}. {1}{2}" -f [int]$matches[2],$matches[1].Trim(),$_.Extension} -WhatIf

问了几天后,我正好弄明白了。

-replace 语法中的 $number 捕获组引用仅仅是文字字符串!

Powershell 从不将它们视为特殊的东西,但 Regex 引擎会。看下面的例子:

$array = "z", "fg"  
$array -replace "(\w{1,2})", ''.Length
#output: 2
#        2

看起来很奇怪?为什么 </code> 捕获组的长度都为 2,"z" 和 "fg"?答案是计算的长度是字符串 <strong><code> 而不是 "z","fg"!
我们再看一个例子,这次我们替换捕获组中的一个字母,看看会发生什么:

$array -replace "(\w{1,2})", ''.Replace("z", "6")
#output: z
#        fg

输出显示 .replace 不适用于捕获组 1。

$array -replace "(\w{1,2})", ''.Replace("1", "6")
#output: 
#        

看到了吗?被替换的字符串是 </code> 本身。<br> 现在应该明白 <code>.padleft 问题的原因了。 PS 填充文字字符串 </code> 并用组的内容显示结果。<br> 当我用 <code>.Padleft(2, "0") 填充它时,没有任何反应,因为“$1”本身的长度为 2。

$array -replace "(\w{1,2})", ''.PadLeft(2, "0")
# output: z
#         fg

如果相反,我用 .Padleft(3, "0") 填充它,这次填充方法确实生效,它将额外的“0”应用到 </code> 但显示结果前面有“0” <code>.

的内容
$array -replace "(\w{1,2})", ''.PadLeft(3, "0")
#output: 0z
#        0fg