2016-11-04 72 views

回答

2

假設的PowerShell 3.0版或更新版本,您可以使用ConvertFrom-StringData cmdlet來解析鍵值對你的ini文件,但你需要過濾掉[default]指令:

# grab relevant lines from file 
$KeyValPairs = Get-Content .\values.ini | Where {$_ -like "*=*" } 

# join strings together as one big string 
$KeyValPairString = $KeyValPairs -join [Environment]::NewLine 

# create hashtable/dictionary from string with ConvertFrom-StringData 
$Dictionary = $KeyValPairString |ConvertFrom-StringData 

然後,您可以使用[regex]::Replace()方法進行查找對字典的每場比賽要更換:

Get-Content .\foo.txt |ForEach-Object { 
    [Regex]::Replace($_, '%(\p{L}+)%', { 
     param($Match) 

     # look term up in dictionary 
     return $Dictionary[$Match.Groups[1].Value] 
    }) 
} 
1

爲了補充Mathias R. Jessen's excellent answer與也採取限制值,以一個特定的INI文件考慮的後來要求改變各種途徑(PSV2 +,除了Get-Content -Raw;在PSV2,使用(Get-Content ...) -join "`n"代替)

使用PsIni\Get-IniContent[environment]::ExpandEnvironmentVariables()

# Translate key-value pairs from section the section of interest 
# into environment variables. 
# After this command, the following environment variables are defined: 
#  $env:A, with value 1 (cmd.exe equivalent: %A%) 
#  $env:B, with value 2 (cmd.exe equivalent: %B%) 
#  $env:C, with value 3 (cmd.exe equivalent: %C%) 
$section = 'default' # Specify the INI-file section of interest. 
(Get-IniContent values.ini)[$section].GetEnumerator() | 
    ForEach-Object { Set-Item "env:$($_.Name)" -Value $_.Value } 

# Read the template string as a whole from file foo.txt, and expand the 
# environment-variable references in it, using the .NET framework. 
# With the sample input, this yields 
# "Now is the 1 for 1 2 men to come to the 3 of their 3". 
[environment]::ExpandEnvironmentVariables((Get-Content -Raw foo.txt)) 

的第三方Get-IniContent cmdlet,後者方便地讀取INI文件(*.ini)到嵌套,有序的哈希表,可以很容易地從一個升高的控制檯(或者,添加-Scope CurrentUser)與Install-Module PsIni安裝,如果你有PS V5 +(或V3或V4與PackageManagement安裝)。

該解決方案利用佔位符(例如%a%)看起來像cmd.exe樣式的環境變量引用這一事實。

注意假設和注意事項

  • 所有ini文件鍵/佔位符名稱是合法的環境變量名。
  • 預存變量可以被覆蓋,其可以是與名稱,如PATH問題。
  • 跨平臺的警告:在類Unix平臺,環境變量引用區分大小寫,因此該解決方案將無法工作同樣存在。

使用自定義INI文件的解析和[environment]::ExpandEnvironmentVariables()

如果安裝的INI文件解析模塊是不是一種選擇,下面的解決方案使用 - 相當複雜的 - 正則表達式通過-replace運算符提取感興趣的部分。

$section = 'default' # Specify the INI-file section of interest. 
# Get all non-empty, non-comment lines from the section using a regex. 
$sectLines = (Get-Content -Raw values.ini) -replace ('(?smn)\A.*?(^|\r\n)\[' + [regex]::Escape($section) + '\]\r\n(?<sectLines>.*?)(\r\n\[.*|\Z)'), '${sectLines}' -split "`r`n" -notmatch '(^;|^\s*$)' 
# Define the key-value pairs as environment variables. 
$sectlines | ForEach-Object { $tokens = $_ -split '=', 2; Set-Item "env:$($tokens[0].Trim())" -Value $tokens[1].Trim() } 

# Read the template string as a whole, and expand the environment-variable 
# references in it, as before. 
[environment]::ExpandEnvironmentVariables((Get-Content -Raw foo.txt)) 
-1

我發現使用這個INI script稱爲獲取-IniContent一個簡單的解決方案。

#read from Setup.ini 
$INI = Get-IniContent .\Setup.ini 
$sec="setup" 

#REPLACE VARIABLES 
foreach($c in Get-ChildItem -Path .\Application -Recurse -Filter *.config) 
{ 
    Write-Output $c.FullName 
    Write-Output $c.DirectoryName 

    $configFile = Get-Content $c.FullName -Raw 
    foreach($v in $INI[$sec].Keys) 
    { 
    $k = '%'+$v+'%' 
    $match = [regex]::IsMatch($configFile, $k) 
    if($match) 
    { 
     $configFile = $configFile -ireplace [regex]::Escape($k), $INI[$sec][$v] 
    } 
    } 
    Set-Content $c.FullName -Value $configFile 
} 
+0

通過'安裝-Module'的'PsIni'模塊,也可以從[PowerShell的畫廊(https://www.powershellgallery.com/packages/PsIni),是一個偉大的發現,但請不要(a)悄悄地擴展你的原始問題的範圍(適當的INI解析限於一個_specific section_),(b)包含相當多的與你的具體問題無關的額外代碼(至少不是沒有解釋),(c)使用文件名和其他標識符不同於你的問題。 – mklement0

+0

雖然'Get-IniContent'的使用確實是一個有用的簡化,但替換模板字符串中的佔位符的代碼比Mathias的答案中的技術更加冗長且效率更低。 – mklement0

相關問題