根据下一行查找并替换为PowerShell
我正试图通过PowerShell查找和替换我要替换的行的下一行上的内容。例如,以下文本文件: blahblah flimflam zimzam 如果下一行不是根据下一行查找并替换为PowerShell,powershell,replace,Powershell,Replace,我正试图通过PowerShell查找和替换我要替换的行的下一行上的内容。例如,以下文本文件: blahblah flimflam zimzam 如果下一行不是flimflam,请不要执行任何操作 我有一个想法,就是用“新东西”来代替“废话”,但我无法让它发挥作用。不过,我想我可能会对包含新行字符的内容感兴趣。使用带a的正则表达式,您甚至可以在不知道该行内容的情况下替换上一行: (Get-Content .\SO_53398250.txt -raw) -replace "(?sm)^[^`r`
flimflam
,请不要执行任何操作
我有一个想法,就是用“新东西”来代替“废话”,但我无法让它发挥作用。不过,我想我可能会对包含新行字符的内容感兴趣。使用带a的正则表达式,您甚至可以在不知道该行内容的情况下替换上一行:
(Get-Content .\SO_53398250.txt -raw) -replace "(?sm)^[^`r`n]+(?=`r?`nflimflam)","new stuff"|
Set-Content .\SO_53398250_2.txt
请参阅上解释的正则表达式(使用不同的转义`n=>\n)- 当您使用
时,通常更容易使用System.IO.StreamReader
将文件作为一个单行、多行字符串完整地读入内存Get Content-Raw
- 如果性能是一个问题,您仍然可以直接使用.NET类型,在这种情况下,
是一个更简单的选择[System.IO.File]::ReadAllText($myFile.FullName)
- 要明确指定输入文件的编码,请使用
/Get encoding-encoding
,[System.IO.file]::ReadAllText($myFile.FullName,)
- 如果性能是一个问题,您仍然可以直接使用.NET类型,在这种情况下,
类型的[string]
方法仅限于文本字符串替换,因此高级匹配(例如将匹配限制为整行)不是一个选项.Replace()
- 使用PowerShell基于正则表达式的
操作符-replace
- 为了避免与PowerShell在双引号(
)字符串中的字符串扩展(字符串插值)混淆,通常最好使用“…”
替换为单引号(-将
)字符串,PowerShell将其视为文本,因此您可以关注字符串中的正则表达式构造“…”
- 使用PowerShell基于正则表达式的
使用内联选项(?m)
(多行)使锚定m
/^
匹配每行的开始/结束(而不是整个字符串)$
是一个前瞻性断言,它在不将匹配部分包含在整体匹配中的情况下进行匹配,因此不会被替换(?=…)
是一种与平台无关的方法,用于匹配换行符序列/字符:Windows上的CRLF(\r?\n
),类Unix平台上的LF only(\r\n
)\n
替换字符串
语法
替换找到的字符串之前的字符串:
'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
替换找到的字符串之前的第二个字符串:
'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
替换找到的字符串后的字符串:
'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
替换找到的字符串后的第二个字符串:
'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
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String T X 1
One
Two
X
X
Five
替换包含T
的(两)个字符串之后的字符串:
'One', 'Two', 'Three', 'Four', 'Five' | Replace-String T X -1
X
X
Three
Four
Five
'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
(来自管道)要匹配和替换的字符串流
-匹配
要在流中匹配的字符串。
请注意,
-Match
运算符用于此参数,这意味着它支持正则表达式。如果整个字符串需要匹配,请使用,例如:-匹配“^Three$”
-更换
用于替换目标的字符串
-Offset=0
相对于要替换的匹配字符串的字符串偏移量。默认值为
0
,意思是:替换匹配的字符串
背景
此cmdlet中编程的一些背景知识:
- (
,Begin{…}
,Process{…}
用于尽可能快地通过cmdlet传递字符串,并将其释放给管道中的下一个cmdlet。此cmdlet是为管道的中间部分设计的(例如End{…}
).要利用管道:Get Content$myFile | Replace String a B 1 |
- 避免使用括号(如:
($List)|替换字符串A B
- 避免分配输出(例如:
$Array=…|替换字符串A B
- 避免读取整个内容的参数(如
)Get content-Raw
- 避免使用括号(如:
- 如果这两种情况都发生(使用负偏移量替换后方,或使用正偏移量替换前方),则需要偏移量大小的缓冲区(
)$buffer=New Object String[]([Math]::Abs($offset))
- 为了加快进程,脚本在缓冲区中循环(
),而不是移动包含的项$buffer[$Count%$Offset]
将保留第一个输入字符串(等于偏移量),因为只有在以后才能确定是否需要替换输入字符串如果($Count-ge-$Offset){…
- 最后(
),如果end{…
为负,则缓冲区(包含其余输入字符串)将被释放。换句话说,负偏移量(例如$Offset
)将缓冲-Offset-$n
字符串,并导致输出在输入流后面运行$n
字符串$n
flimflam
(在彼此之后),例如:'blahblah',flimflam',flimflam',zimzam'
?