2023年12月21日 星期四

PowerShell 如何讀取解析 Env/Properties 檔案

PowerShell 如何讀取解析 Env/Properties 檔案

實作做的功能包含了

  1. 自動讀取 “.env”, “.env.development”, “.env.production” 三個檔案,優先順序是後面覆蓋前面,同檔案間優先順序也是後面覆蓋前面
  2. 支援擴充功能使用斜線換行
  3. 支援擴充功能雙引號解析 PowerShell 變數


為什麼要拆分這麼多env檔案主要是兩個觀點

  1. 把連接資訊放在“.env.production”中避免部署設置時不小心動到連接資訊。
  2. 拆分development跟production,僅共用.env檔案這樣可以很好的區分開發機跟生產環境


範例 .env

A1="  AAA  
A2=  AAA  "
B1=" AAA "
B2=' AAA '
C1= \
arr1,\
arr2
D1="$($env:USERNAME)"
D2='$($env:USERNAME)'
Z=\
A\
B\
C\
D\


讀取用函式
ConvertFrom-Env.ps1

# 轉換 Env 文件
function ConvertFrom-Env {
    param (
        [string[]]$EnvFiles = @(".env", ".env.development", ".env.production"),
        [System.Text.Encoding]$Encoding = [System.Text.Encoding]::Default
    )

    # 使用有序字典保持讀取的順序
    $envVariables = [Ordered]@{}

    function ProcessLine {
        param (
            [string]$line
        )

        # 忽略註釋行
        if ($line -and -not $line.StartsWith("#")) {
            if ($line -match "^\s*([^#=]+?)\s*=\s*(.*)$") {
                $key = $matches[1].Trim()
                $value = $matches[2]
                if ($value -match '^"(.+)"$') {
                    # 處理雙引號包圍的值並展開字符串
                    $value = $matches[1] -replace '\\n', "`n" -replace '\\r', "`r" -replace '\\t', "`t"
                    $value = $ExecutionContext.InvokeCommand.ExpandString($value)
                } elseif ($value -match "^'(.+)'$") {
                    # 處理單引號包圍的值
                    $value = $matches[1]
                } else {
                    $value = $value.Trim()
                }

                # 將解析後的鍵值對加入字典
                $envVariables[$key] = $value
            }
        }
    }

    # 遍歷所有指定的文件
    foreach ($file in $EnvFiles) {
        if (Test-Path $file) {
            try {
                $reader = New-Object System.IO.StreamReader -ArgumentList $file, $Encoding
                try {
                    $currentLine = ''
                    while ($null -ne ($line = $reader.ReadLine())) {
                        $trimmedLine = $line.Trim()
                        if ($trimmedLine.EndsWith('\')) {
                            # 跨行值的處理
                            $currentLine += $trimmedLine.TrimEnd('\').TrimEnd()
                            continue
                        } else {
                            $currentLine += $trimmedLine
                        }
                        ProcessLine -line $currentLine
                        $currentLine = ''
                    }
                    # 處理跨行結尾在最一行時沒被處理的剩餘值
                    if ($currentLine) { ProcessLine -line $currentLine }
                } finally {
                    $reader.Close()
                }
            } catch {
                Write-Warning "無法讀取文件 '$file': $_"
            }
        }
    } # $envVariables = [PSCustomObject]$envVariables
    return $envVariables
} ConvertFrom-Env


代碼開源於此: hunandy14/ConvertFrom-Env (github.com)






沒有留言:

張貼留言