所以我使用的脚本看起来像这样。它工作得很好,唯一的问题是它正在计算行号,我只是想让它每次用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'}