我有一个文件列表,所有文件的扩展名.pkg都是产品的一部分。在每个文件中都有一段看起来像这样的文本:
//VERSION
1.73
//END VERSION
我正在尝试编写一个PowerShell脚本,它将找到该代码块并将1.73替换为1.74。
//VERSION
1.74
//END VERSION
我发现以下内容,但我似乎无法使用正则表达式部分写入来识别代码块。
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$dir = $scriptPath + "\Sandbox\"
Write-Host "*** Modifying Files In $dir to Update Version ***"
Get-ChildItem -Path $dir | ?{$_.Extension -eq ".pkg"} |
ForEach-Object {
$copyto = $dir + $_
# Load the file's contents, replace commas with spaces
(Get-Content $copyto) -replace '(?<=//VERSION\r").*?(?="\r//END VERSION)', '1.73' |
# and write it to the correct folder and file name
Out-File $copyto
}
我知道基本语法有效,因为我使用这个完全相同的代码来循环并替换更容易识别的其他内容。
更新的工作代码
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$dir = Join-Path $scriptPath "Sandbox"
Write-Host "*** Modifying Files In $dir to Update Version ***"
Get-ChildItem -Path $dir | ?{$_.Extension -eq ".pkg"} |
ForEach-Object {
$copyto = Join-Path $dir $_
$foundLine = $false
Get-Content $copyto | foreach {
if ($foundLine) {
# Flag is set. Output the following instead of the line from the file
'1.74'
# And clear the flag
$foundLine = $false
} else {
# Output current line
$_
# If we find the version line, set the flag so that
# we enter the replacement on the next line.
if ($_ -eq '//VERSION') {
$foundLine = $true
}
}
} | Out-File ($copyto + '.new')
Write-Host "*** Deleting $copyto ***"
Remove-Item $copyto
Write-Host "*** Renaming ($copyto + '.new') ***"
Rename-Item -Path ($copyto + '.new') -NewName $copyto
}
答案 0 :(得分:1)
默认情况下,Get-Content
将文件作为字符串数组返回。每行都会针对您的正则表达式进行独立检查。由于您尝试匹配的模式跨越多行,因此没有任何一行会匹配整个行。
要将整个文件视为包含嵌入换行符的一个字符串,请传递-Raw
参数
(Get-Content $copyto -Raw) -replace ...
这是一种替代解决方案,它逐行操作并且不使用正则表达式。对于不熟悉正则表达式的人来说,输入更长,但更容易理解。
$foundLine = $false
Get-Content $copyto | foreach {
if ($foundLine) {
# Flag is set. Output the following instead of the line from the file
'1.74'
# And clear the flag
$foundLine = $false
} else {
# Output current line
$_
# If we find the version line, set the flag so that
# we enter the replacement on the next line.
if ($_ -eq '//VERSION') {
$foundLine = $true
}
}
} | Out-File ($copyto + '.new')
不相关:在连接路径时,首选Join-Path
进行字符串连接。它有助于避免错过反斜杠问题,并使您的代码更加健壮。
$dir = Join-Path $scriptPath "Sandbox"
...
$copyto = Join-Path $dir $_
答案 1 :(得分:1)
就像Ryan向您展示的那样,您必须使用-raw
开关来获取Get-Content cmdlet。但是,正则表达式中还有一些错误:
\r?\n
来读取新行。 所以替换这一行:
(Get-Content $copyto -raw) -replace '(?<=\/\/VERSION)(\r?\n).*?(\r?\n)(?=\/\/END VERSION)', '${1}1.74${2}'