这个问题要求尽可能多地支持流式传输的可重用 cmdlet...
Replace-String
Function Replace-String {
[CmdletBinding()][OutputType([String[]])]Param (
[String]$Match, [String]$Replacement, [Int]$Offset = 0,
[Parameter(ValueFromPipeLine = $True)][String[]]$InputObject
)
Begin {
$Count = 0
$Buffer = New-Object String[] ([Math]::Abs($Offset))
}
Process {
$InputObject | ForEach-Object {
If ($Offset -gt 0) {
If ($Buffer[$Count % $Offset] -Match $Match) {$Replacement} Else {$_}
} ElseIf ($Offset -lt 0) {
If ($Count -ge -$Offset) {If ($_ -Match $Match) {$Replacement} Else {$Buffer[$Count % $Offset]}}
} Else {
If ($_ -Match $Match) {$Replacement} Else {$_}
}
If ($Offset) {$Buffer[$Count++ % $Offset] = $_}
}
}
End {
For ($i = 0; $i -gt $Offset; $i--) {$Buffer[$Count++ % $Offset]}
}
}
语法
$InputObject | Replace-String [-Match] <String to find>
[-Replacement] <Replacement string to use>
[-Offset] <Offset relative to the matched string>
示例:
替换找到的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String Three X 0
One
Two
X
Four
Five
替换找到的字符串之前的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String Three X -1
One
X
Three
Four
Five
替换找到的字符串之前的第二个字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String Three X -2
X
Two
Three
Four
Five
替换找到的字符串后面的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String Three X 1
One
Two
Three
X
Five
替换找到的字符串之后的第二个字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String Three X 2
One
Two
Three
Four
X
替换包含T的(两个)字符串之前的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String T X -1
X
X
Three
Four
Five
替换包含T的(两个)字符串之后的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String T X 1
One
Two
X
X
Five
具体问题:
'blahblah', 'flimflam','zimzam' | Replace-String 'flimflam' 'new stuff' -1
new stuff
flimflam
zimzam
参数
-InputObject <String[]>(来自管道)
要匹配和替换的字符串流
-Match <String>
流中要匹配的字符串。
请注意,-Match 运算符用于此参数,这意味着它支持正则表达式。如果整个字符串需要匹配,请使用start line and end line anchors,例如:-Match '^Three$'。
-Replacement <String>
用于替换目标的字符串。
-Offset <Int> = 0
相对于要替换的匹配字符串的字符串偏移量。默认为0,意思是:替换匹配的字符串。
背景
有关此 cmdlet 编程的一点背景知识:
-
Input Processing Methods(
Begin {...}、Process {...}、End {...} 用于通过 cmdlet 尽可能快地传递字符串并将它们释放到管道中的下一个 cmdlet。这个 cmdlet 是为中间管道(例如Get-Content $myFile | Replace-String A B 1 | ...)。从管道中利用:
- 避免使用括号(例如:
($List) | Replace-String A B
- 避免分配输出(例如:
$Array = ... | Replace-String A B
- 避免读取整个内容的参数(如
Get-Content -Raw)
- 如果这两种情况(替换后面 - 使用负偏移量 - 或前面 - 使用正偏移量 -),则需要偏移大小的缓冲区 (
$Buffer = New-Object String[] ([Math]::Abs($Offset)))
- 为了加快处理速度,脚本循环通过缓冲区 (
$Buffer[$Count % $Offset]) 而不是移动包含的项目
-
If ($Count -ge -$Offset) {... 将保存输入字符串的第一个数量(等于偏移量),因为它只能在以后确定是否需要替换输入字符串
- 最后 (
End {...),如果 $Offset 为负数,则缓冲区(包含其余输入字符串)将被释放。换句话说,负偏移量(例如-offset -$n)将缓冲$n 字符串并导致输出在输入流后面运行$n 字符串