使用powershell和regexp替换整行文本?

时间:2022-02-12 19:15:17

I have a programming background, but I am fairly new to both powershell scripting and regexp. Regexp has always eluded me, and my prior projects have never 'forced' me to learn it.

我有编程背景,但我对PowerShell脚本和regexp都很新。 Regexp总是让我望而却步,而我以前的项目从未“强迫”我学习它。

With that in mind I have a file with a line of text that I need to replace. I can not depend on knowing where the line exists, if it has whitespace in front of it, or what the ACTUAL text being replaced IS. I DO KNOW what will preface and preceed the text being replaced.

考虑到这一点,我有一个文件,我需要替换一行文本。我不能依赖于知道该行存在的位置,它前面是否有空格,或者被替换的ACTUAL文本是什么。我知道在替换文本的前言和先例。

AGAIN, I will not KNOW the value of "Replace This Text". I will only know what prefaces it "" and what preceeds it "". Edited OP to clarify. Thanks!

再说一遍,我不会知道“替换此文本”的价值。我只会知道它的前言是什么,以及它之前是什么“”。编辑OP澄清。谢谢!

LINE OF TEXT I NEED TO REPLACE

我需要替换的文字行

<find-this-text>Replace This Text</find-this-text>

POTENTIAL CODE

潜在的代码

(gc $file) | % { $_ -replace “”, “” } | sc $file
  • Get the content of the file, enclose this in parentheses to ensure file is first read and then closed so it doesnt throw an error when trying to save the file.

    获取文件的内容,将其括在括号中以确保首先读取文件然后关闭,以便在尝试保存文件时不会引发错误。

  • Iterate through each line, and issue replace statement. THIS IS WHERE I COULD USE HELP.

    遍历每一行,并发出替换语句。这是我可以使用帮助的地方。

  • Save the file by using Set-Content. My understanding is that this method is preferable, because it takes encoding into consideration,like UTF8.

    使用Set-Content保存文件。我的理解是这种方法更可取,因为它需要考虑编码,如UTF8。

2 个解决方案

#1


4  

XML is not a line oriented format (nodes may span several lines, just as well as a line may contain several nodes), so it shouldn't be edited as if it were. Use a proper XML parser instead.

XML不是面向行的格式(节点可能跨越多行,就像一行可能包含多个节点一样),因此不应该像它那样进行编辑。请改用适当的XML解析器。

$xmlfile = 'C:\path\to\your.xml'

[xml]$xml = Get-Content $xmlfile
$node = $xml.SelectSingleNode('//find-this-text')
$node.'#text' = 'replacement text'

For saving the XML in "UTF-8 without BOM" format you can call the Save() method with a StreamWriter doing The Right Thing™:

要以“UTF-8无BOM”格式保存XML,您可以使用StreamWriter调用Save()方法,使用正确的Thing™:

$UTF8withoutBOM = New-Object Text.UTF8Encoding($false)
$writer = New-Object IO.StreamWriter ($xmlfile, $false, $UTF8withoutBOM)
$xml.Save($writer)
$writer.Close()

#2


2  

The .* in the regular expression would be considered "greedy" and dangerous by many. If the line that contains this tag and it's data contains nothing else, then there really isn't any significant risk according to my understanding.

正则表达式中的。*将被视为“贪婪”并且很多人都很危险。如果包含此标记的行及其数据不包含任何其他内容,那么根据我的理解,确实没有任何重大风险。

$file = "c:\temp\sms.txt"
$OpenTag = "<find-this-text>"
$CloseTag = "</find-this-text>"
$NewText = $OpenTag + "New text" + $CloseTag

(Get-Content $file) | Foreach-Object {$_ -replace "$OpenTag.*$CloseTag", $NewText} | Set-Content $file

#1


4  

XML is not a line oriented format (nodes may span several lines, just as well as a line may contain several nodes), so it shouldn't be edited as if it were. Use a proper XML parser instead.

XML不是面向行的格式(节点可能跨越多行,就像一行可能包含多个节点一样),因此不应该像它那样进行编辑。请改用适当的XML解析器。

$xmlfile = 'C:\path\to\your.xml'

[xml]$xml = Get-Content $xmlfile
$node = $xml.SelectSingleNode('//find-this-text')
$node.'#text' = 'replacement text'

For saving the XML in "UTF-8 without BOM" format you can call the Save() method with a StreamWriter doing The Right Thing™:

要以“UTF-8无BOM”格式保存XML,您可以使用StreamWriter调用Save()方法,使用正确的Thing™:

$UTF8withoutBOM = New-Object Text.UTF8Encoding($false)
$writer = New-Object IO.StreamWriter ($xmlfile, $false, $UTF8withoutBOM)
$xml.Save($writer)
$writer.Close()

#2


2  

The .* in the regular expression would be considered "greedy" and dangerous by many. If the line that contains this tag and it's data contains nothing else, then there really isn't any significant risk according to my understanding.

正则表达式中的。*将被视为“贪婪”并且很多人都很危险。如果包含此标记的行及其数据不包含任何其他内容,那么根据我的理解,确实没有任何重大风险。

$file = "c:\temp\sms.txt"
$OpenTag = "<find-this-text>"
$CloseTag = "</find-this-text>"
$NewText = $OpenTag + "New text" + $CloseTag

(Get-Content $file) | Foreach-Object {$_ -replace "$OpenTag.*$CloseTag", $NewText} | Set-Content $file