2013-03-27 10 views
5

Ich arbeite an einem Powershell-Skript, das Konfigurationsdateien ändert. Ich habe Dateien wie folgt aus:Powershell-Funktion zum Ersetzen oder Hinzufügen von Zeilen in Textdateien

##################################################### 
# comment about logentrytimeout 
##################################################### 
Logentrytimeout= 1800 

, die wie folgt aussehen sollte:

##################################################### 
# comment about logentrytimeout 
##################################################### 
Logentrytimeout= 180 
disablepostprocessing = 1 
segmentstarttimeout = 180 

Wenn es einen Schlüsselsatz (Logentrytimeout) ist, aktualisieren Sie es nur auf den angegebenen Wert. Kommentare ignorieren, wo der Schlüssel erwähnt wird (Zeilen, die mit # beginnen). Der Schlüssel unterscheidet nicht zwischen Groß- und Kleinschreibung.

Wenn der Schlüssel nicht gesetzt ist (disablepostprocessing und segmentstarttimeout), hängen Sie Schlüssel und Wert an die Datei an. Meine Funktion so geht weit wie folgt aus:

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" 
  • Was ist die richtige Regex?
  • Wie überprüfe ich, ob es einen Ersatz gab?
  • Wenn es keinen Ersatz gab: Wie kann ich dann $ key + "=" + $ Wert an die Datei anhängen?

Antwort

13

Unter der Annahme, die $key Sie ersetzen möchten immer am Anfang einer Zeile ist, und daß es keine speziellen regex Zeichen

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" 

Wenn kein Ersatz wird $key = $value an die Datei angehängt.

2

ich dies tun würde:

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: hat einen Ersatz Glocke, und ein nicht pfeifen lassen.

1

Ändern Sie die Funktion dazu:

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)   
    } 
} 

Dann, wenn Sie die Funktion aufrufen, verwenden Sie dieses Format:

Set-Config -file "divider.conf" -key "Logentrytimeout" -value "180" 

Edit: Ich habe vergessen, Ihre Anforderung die Linie hinzufügen, wenn es nicht der Fall ist existieren. Dies wird für die $key überprüfen, wenn es existiert wird es seinen Wert auf $value setzen. Wenn es nicht existiert, fügt es am Ende der Datei $key = $value hinzu. Ich habe die Funktion auch umbenannt, um den Namenskonventionen der Power Shell besser zu entsprechen.

3

Aktualisierte Version der obigen Funktionen mit einigen Parametrierung und ausführliche Ausgabe, falls erforderlich.

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" 
    } 
} 
0

@CarlR Funktion es für Powershell-Version 3. ist das es das gleiche zu Powershell Version 2 angepasst ist.

EDIT: Changed regulären Ausdruck zwei Fehler auf Set-FileConfigurationValue zu beheben:

  1. Wenn Sie eine Zeile wie dieses:

    ; This is a Black line

    Und Sie versuchen zu tun:

    Set-FileConfigurationValue $configFile "Black" 20 -ReplaceExistingValue

    Sie erhalten eine Nachricht über "Ersetzen", aber nichts passiert.

  2. Wenn Sie zwei Zeilen wie diese:

    filesTmp = 50
    Tmp = 50

    Und Sie versuchen zu tun:

    Set-FileConfigurationValue $configFile "Tmp" 20 -ReplaceExistingValue

    Sie erhalten die beiden Linien geändert !

    filesTmp = 20 Tmp = 20

Dies ist die letzte Version:

Function Set-FileConfigurationValue() 
{ 
    [CmdletBinding()] 
    param(
     [Parameter(Mandatory=$True)] 
     [ValidateScript({Test-Path $_})] 
     [string] $Path, 
     [Parameter(Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string] $Key, 
     [Parameter(Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string]$Value, 
     [Switch] $ReplaceExistingValue, 
     [Switch] $ReplaceOnly 
    ) 

    $regmatch= $("^($Key\s*=\s*)(.*)") 
    $regreplace=$('${1}'+$Value) 

    if ((Get-Content $Path) -match $regmatch) 
    { 
     If ($ReplaceExistingValue) 
     { 
      Write-Verbose "Replacing configuration Key ""$Key"" in configuration file ""$Path"" with Value ""$Value""" 
      (Get-Content -Path $Path) | ForEach-Object { $_ -replace $regmatch,$regreplace } | 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" 
    } 
} 

Außerdem habe ich eine Funktion aus der Konfigurationsdatei lesen

Function Get-FileConfigurationValue() 
{ 
    [CmdletBinding()] 
    param(
     [Parameter(Mandatory=$True)] 
     [ValidateScript({Test-Path $_})] 
     [string] $Path, 
     [Parameter(Mandatory=$True)] 
     [ValidateNotNullOrEmpty()] 
     [string] $Key, 
     [Parameter(Mandatory=$False)] 
     [ValidateNotNullOrEmpty()] 
     [string]$Default="" 
    ) 

    # Don't have spaces before key. 
    # To allow spaces, use "$Key\s*=\s*(.*)" 
    $regKey = $("^$Key\s*=\s*(.*)") 

    # Get only last time 
    $Value = Get-Content -Path $Path | Where {$_ -match $regKey} | Select-Object -last 1 | ForEach-Object { $matches[1] } 
    if(!$Value) { $Value=$Default } 

    Return $Value 
} 
0
function sed($filespec, $search, $replace) 
{ 
    foreach ($file in gci -Recurse $filespec | ? { Select-String $search $_ -Quiet }) 
    { 
    (gc $file) | 
    ForEach-Object {$_ -replace $search, $replace } | 
    Set-Content $file 
    } 
} 

Verbrauch:

sed ".\*.config" "intranet-" "intranetsvcs-" 
Verwandte Themen