Powershell5 Compact代码通过组合foreach,begin,process和replace命令

问题描述 投票:2回答:1

用更少的代码可以获得相同的结果吗?代码在sample.bat中搜索字符串AROUND LINE {1-9999}和LINE2 {1-9999},并将{1-9999}替换为代码所在的{line number}。

sample.bat:

AROUND LINE 262
LINE2 1964

旧代码:

gc $env:temp\sample.bat | foreach -Begin {$lc = 1} -Process {
  $_ -replace "AROUND LINE \d*", "AROUND LINE $lc";
  $lc += 1
} | Out-File -Encoding Ascii $env:temp\results.bat
(gc $env:temp\results.bat) | foreach -Begin {$lc = 1} -Process {
  $_ -replace "LINE2 \d*", "LINE2 $lc";
  $lc += 1
} | Out-File -Encoding Ascii $env:temp\results.bat

当前代码:

(gc $env:temp\sample.bat) | foreach -Begin {$lc = 1} -Process {
  $_ -replace "AROUND LINE \d*", "AROUND LINE $lc";
  $lc += 1
} | foreach -Begin {$lc = 1} -Process {
  $_ -replace "LINE2 \d*", "LINE2 $lc";
} | Out-File -Encoding Ascii $env:temp\sample.bat

预期成绩:

AROUND LINE 1
LINE2 2

实际结果:

AROUND LINE 1
LINE2 2
powershell powershell-v5.0
1个回答
1
投票

你可以使用一个正则表达式来完成这项工作:

gc $env:temp\sample.bat | foreach -Begin {$lc = 1} -Process {
  $_ -replace '(?<=AROUND LINE |LINE2 )\d+', $lc++
} | Set-Content -Encoding Ascii $env:temp\results.bat

请注意,我使用'...'(单引号)而不是"..."(双引号)来包含正则表达式,这更好地排除了PowerShell首先执行字符串扩展(插值)引起的潜在混淆。 $lc++返回当前的$lc值并随后将其增加1,从而避免了对$lc += 1语句的需要。 另外,我用Out-File替换了Set-Content,因为它们在保存字符串方面功能相同,但后者更快。 最后,要匹配一个或多个数字,请使用\d+而不是\d*

关于$_ -replace '(?<=AROUND LINE |LINE2 )\d+', $lc++的说明:

  • 正则表达式(?<=AROUND LINE |LINE2 )\d+使用一个后视断言((?<=...)寻找(|)字符串AROUND LINE 或字符串LINE2 beforefore一个或多个(+)数字(\d)。 后视断言在设计上不被认为是匹配的一部分,因此被替换的子串限于数字的运行,即仅数字。
  • $lc++是替换操作数:它返回变量$lc的当前值,然后递增其值;请注意,即使$lc是一个数字([int]),PowerShell会自动将其转换为字符串以进行替换。

但一般来说,你可以简单地链接-replace操作:

# ...
$_ -replace 'AROUND LINE \d+', "AROUND LINE $lc" -replace 'LINE2 \d+', "LINE2 $lc"
++$lc
# ... 
© www.soinside.com 2019 - 2024. All rights reserved.