每次替换字符串时递增一个数字



所以我使用的脚本看起来像这样。它工作得很好,唯一的问题是它正在计算行号,我只是想让它每次用1 2 3 4等代替num,而不是像这样5 20 25等,这是因为它似乎是计数和增加$c为每行,而不是每次它替换字符串num。

$c=0
(Get-Content C:UsersHDesktop3.txt) | 
Foreach-Object {$_ -replace "num", $((++$c))}  | 
Out-File C:UsersHDesktop4.txt

试试这个:

$c = [ref] 0
$text = Get-Content 'C:UsersHDesktop3.txt' -Raw
[regex]::Replace( $text, 'num', { (++$c.Value) } ) |
Set-Content 'C:UsersHDesktop4.txt'
# With PowerShell 6+ you could write:
# (Get-Content 'C:UsersHDesktop3.txt' -Raw) -replace 'num', { (++$c.Value) } |
#    Set-Content 'C:UsersHDesktop4.txt'

Copy-pastable演示:

$text = @'
num foo num
bar num bar
num baz num
'@ 
$c = [ref] 0
[regex]::Replace( $text, 'num', { (++$c.Value) } )
# With PowerShell 6+ you could write:
# $text -replace 'num', { (++$c.Value) }
输出:

1 foo 2
bar 3 bar
4 baz 5

解释:

  • 使用引用类型([ref])变量而不是普通变量。传递给[regex]::Replace()-replace的scriptblock(仅限ps6 +)在子作用域中运行,因此它不能直接修改父作用域中的变量。您可以修改引用类型的成员,这就是[ref]技巧起作用的原因。除了[ref],你还可以使用[PSCustomObject][Hashtable](两者都是引用类型)和计数器成员。
  • 表达式++$c.Value周围的括号需要输出表达式的值,默认情况下不产生输出。你已经有了,我只是向其他访客解释一下。
  • 使用Get-Content和参数-Raw可以更快,因为文件的内容以单个多行字符串的形式输出,而不是以需要更多内存为代价将其分成每行一个字符串。

至于你的尝试:

$_ -replace "num", $((++$c))

您正在传递表达式而不是脚本块作为RHS参数给-replace操作符。此外,-replace操作符的脚本块参数仅从PowerShell 6开始支持。对于旧版本,您必须使用。net函数[Regex]::Replace

对于ForEach-Object"循环"的每次迭代,-replace操作符之前求值一次。因此,您实际上只是在计算文件的行数,而不是模式出现的次数。

只有脚本块的执行可以被延迟。它不会在您定义它的地方立即被调用1,但是当具有[ScriptBlock]参数的函数或操作符决定调用它时,可能会在模式具有多个匹配时多次调用它。要定义一个脚本块,请使用{},就像我在开始的示例中所做的那样。


[1]除非您使用调用或点源操作符,例如&{'foo'}

最新更新