Powershell function to replace or add lines in text files
Solution 1
Assuming the $key
you want to replace is always at the beginning of a line, and that it contains no special regex characters
function setConfig( $file, $key, $value ) {
$content = Get-Content $file
if ( $content -match "^$key\s*=" ) {
$content -replace "^$key\s*=.*", "$key = $value" |
Set-Content $file
} else {
Add-Content $file "$key = $value"
}
}
setConfig "divider.conf" "Logentrytimeout" "180"
If there is no replacement $key = $value
will be appended to the file.
Solution 2
Updated version of the functions above with some parametrisation and verbose output if required.
Function Set-FileConfigurationValue()
{
[CmdletBinding(PositionalBinding=$false)]
param(
[Parameter(Mandatory)][string][ValidateScript({Test-Path $_})] $Path,
[Parameter(Mandatory)][string][ValidateNotNullOrEmpty()] $Key,
[Parameter(Mandatory)][string][ValidateNotNullOrEmpty()] $Value,
[Switch] $ReplaceExistingValue,
[Switch] $ReplaceOnly
)
$content = Get-Content -Path $Path
$regreplace = $("(?<=$Key).*?=.*")
$regValue = $("=" + $Value)
if (([regex]::Match((Get-Content $Path),$regreplace)).success)
{
If ($ReplaceExistingValue)
{
Write-Verbose "Replacing configuration Key ""$Key"" in configuration file ""$Path"" with Value ""$Value"""
(Get-Content -Path $Path) | Foreach-Object { [regex]::Replace($_,$regreplace,$regvalue) } | Set-Content $Path
}
else
{
Write-Warning "Key ""$Key"" found in configuration file ""$Path"". To replace this Value specify parameter ""ReplaceExistingValue"""
}
}
elseif (-not $ReplaceOnly)
{
Write-Verbose "Adding configuration Key ""$Key"" to configuration file ""$Path"" using Value ""$Value"""
Add-Content -Path $Path -Value $("`n" + $Key + "=" + $Value)
}
else
{
Write-Warning "Key ""$Key"" not found in configuration file ""$Path"" and parameter ""ReplaceOnly"" has been specified therefore no work done"
}
}
Solution 3
I'd do this:
function setConfig( $file, $key, $value )
{
$regex = '^' + [regex]::escape($key) + '\s*=.+'
$replace = "$key = $value"
$old = get-content $file
$new = $old -replace $regex,$replace
if (compare-object $old $new)
{
Write-Host (compare-object $old $new | ft -auto | out-string) -ForegroundColor Yellow
$new | set-content $file
}
else {
$replace | add-content $file
Write-Host "$replace added to $file" -ForegroundColor Cyan
}
}
Edit: added a replacement bell, and a not match whistle.
Solution 4
Change the function to this:
function Set-Config( $file, $key, $value )
{
$regreplace = $("(?<=$key).*?=.*")
$regvalue = $(" = " + $value)
if (([regex]::Match((Get-Content $file),$regreplace)).success) {
(Get-Content $file) `
|Foreach-Object { [regex]::Replace($_,$regreplace,$regvalue)
} | Set-Content $file
} else {
Add-Content -Path $file -Value $("`n" + $key + " = " + $value)
}
}
Then when you call the function, use this format:
Set-Config -file "divider.conf" -key "Logentrytimeout" -value "180"
Edit: I forgot your requirement of adding the line if it doesn't exist. This will check for the $key
, if it exists it will set its value to $value
. If it doesn't exist it will add $key = $value
to the end of the file. I also renamed the function to be more consistent with power shell naming conventions.
Comments
-
mles almost 2 years
I'm working on a powershell script that modifies config files. I have files like this:
##################################################### # comment about logentrytimeout ##################################################### Logentrytimeout= 1800
who should look like this:
##################################################### # comment about logentrytimeout ##################################################### Logentrytimeout= 180 disablepostprocessing = 1 segmentstarttimeout = 180
If there is a key set(Logentrytimeout), just update it to the given value. Ignore comments, where the key is mentioned(lines that start with #). The Key is case insensitive.
If the key is not set(disablepostprocessing and segmentstarttimeout), append key and value to the file. My function so far goes like this:
function setConfig( $file, $key, $value ) { (Get-Content $file) | Foreach-Object {$_ -replace "^"+$key+".=.+$", $key + " = " + $value } | Set-Content $file } setConfig divider.conf "Logentrytimeout" "180" setConfig divider.conf "disablepostprocessing" "1" setConfig divider.conf "segmentstarttimeout" "180"
- What is the correct regex?
- How do I check if there was a replacement?
- If there was no replacement: How can I append $key+" = "+$value to the file then?