values.ini 看起来像
[default]
A=1
B=2
C=3
foo.txt 看起来像
Now is the %A% for %a% %B% men to come to the %C% of their %c%
我想使用Powershell搜索 values.ini 中的所有%x%值,然后将 foo.txt 中的每个匹配实例替换为相应的值,不区分大小写;产生以下内容:
Now is the 1 for 1 2 men to come to the 3 of their 3
答案 0 :(得分: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 :(得分: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
)读入嵌套的有序散列表中,可以通过高架控制台轻松安装Install-Module PsIni
(或者,如果您有PS v5 +(或安装了PackageManagement的v3或v4),请添加-Scope CurrentUser
)。
此解决方案利用了占位符(例如%a%
)看起来像cmd.exe
样式的环境变量引用这一事实。
请注意假设和警告:
PATH
等名称而出现问题。 使用自定义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))
答案 2 :(得分:-1)
我使用名为 Get-IniContent 的INI script找到了一个更简单的解决方案。
#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
}