如何阻止PowerShell Out-File覆盖JSON文件中未修改的区块
问题:PowerShell脚本更新JSON文件时意外覆盖非目标环境区块
我有一个包含dev、preprod、prod三个区块的JSON文件,用于存储对应环境下Azure资源(App Reg、安全组等)的信息。编写的PowerShell脚本在创建资源后,会将信息写入JSON的对应环境区块,但存在问题:
- 首次针对
dev运行时,能正确填充dev区块 - 后续针对
preprod运行时,虽能填充preprod区块,但会将dev区块设为null,相当于覆盖了整个文件
我需要脚本仅更新目标环境的区块,保留其他环境的原有内容。当前代码如下:
if ($environment -eq "Development") { $devBlock = @{ "Project" = $projectName "tenant" = $tenantName "AppRegId" = $spdetails.appId "ProjectId" = $projectSubId "projectsubname" = $projectSubName "Date" = $date "Username" = $actor "RoGroup" = $RoGroupid.id "FcGroup" = $FcGroupid.id "environment" = $environment } } elseif ($environment -eq "PreProduction") { $preprodBlock = @{ "Project" = $projectName "tenant" = $tenantName "AppRegId" = $spdetails.appId "ProjectId" = $projectSubId "projectsubname" = $projectSubName "Date" = $date "Username" = $actor "RoGroup" = $RoGroupid.id "FcGroup" = $FcGroupid.id "environment" = $environment } } else { $prodBlock = @{ "Project" = $projectName "tenant" = $tenantName "AppRegId" = $spdetails.appId "ProjectId" = $projectSubId "projectsubname" = $projectSubName "Date" = $date "Username" = $actor "RoGroup" = $RoGroupid.id "FcGroup" = $FcGroupid.id "environment" = $environment } } $data = @{ "dev" = $devBlock "preprod" = $preprodBlock "prod" = $prodBlock } # Convert the hashtable to a JSON string $json = $data | ConvertTo-Json -Depth 10 # Define the path for the JSON file $jsonFilePath = $projectName + ".json" # Write the JSON string to the file $json | Out-File -FilePath $jsonFilePath -Encoding utf8 Write-Output "JSON file created at $jsonFilePath"
解决方案
问题根源:当前脚本每次运行时,仅初始化目标环境的变量,其他环境变量未被赋值(默认是$null),最终生成的哈希表会把非目标区块设为null,覆盖原有文件。
修改思路:
- 先读取现有JSON文件(如果存在),保留已有区块的内容
- 仅更新目标环境的区块数据
- 将更新后的哈希表写回文件
修改后的完整代码:
# 定义JSON文件路径 $jsonFilePath = "$projectName.json" # 初始化数据哈希表:如果文件存在则读取现有内容,否则创建空结构 if (Test-Path $jsonFilePath) { $data = Get-Content $jsonFilePath -Raw | ConvertFrom-Json -AsHashtable } else { $data = @{ "dev" = $null "preprod" = $null "prod" = $null } } # 生成当前环境的区块数据 $currentEnvBlock = @{ "Project" = $projectName "tenant" = $tenantName "AppRegId" = $spdetails.appId "ProjectId" = $projectSubId "projectsubname" = $projectSubName "Date" = $date "Username" = $actor "RoGroup" = $RoGroupid.id "FcGroup" = $FcGroupid.id "environment" = $environment } # 根据环境更新对应区块 switch ($environment) { "Development" { $data["dev"] = $currentEnvBlock } "PreProduction" { $data["preprod"] = $currentEnvBlock } default { $data["prod"] = $currentEnvBlock } } # 转换为JSON并写入文件 $data | ConvertTo-Json -Depth 10 | Out-File -FilePath $jsonFilePath -Encoding utf8 Write-Output "JSON file updated at $jsonFilePath"
关键优化点:
- 使用
Test-Path检查文件是否存在,存在则读取原有内容(ConvertFrom-Json -AsHashtable确保可以修改) - 统一生成环境区块数据,避免重复代码
- 使用
switch语句替代多分支if/else,逻辑更清晰 - 仅更新目标环境的键,保留其他环境的原有内容
内容的提问来源于stack exchange,提问作者Keagan
相关产品推荐
相关产品推荐

