2013-03-27 50 views
5

我正在修改配置文件的PowerShell腳本。我有這樣的文件:PowerShell函數替換或添加文本文件中的行

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

誰應該是這樣的:

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

如果有一個按鍵(Logentrytimeout),只需將其更新到給定值。忽略註釋,提到關鍵字(以#開頭的行)。密鑰不區分大小寫。

如果未設置密鑰(disablepostprocessing和segmentstarttimeout),請將密鑰和值附加到文件。我的功能到目前爲止是這樣的:

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" 
  • 什麼是正確的正則表達式?
  • 如何檢查是否有替換?
  • 如果沒有替換:如何將$ key +「=」+ $ value附加到文件中?

回答

13

假設$key要替換始終處於一行的開頭,並且它不包含特殊字符的正則表達式

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" 

如果沒有替代$key = $value將被添加到該文件。

2

我應該這樣做:

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 
     } 

} 

編輯:增加了更換門鈴,一個無法比擬的哨子。

1

更改的功能如下:

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

然後當你調用該函數,請使用以下格式:

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

編輯:我忘了你的加入行,如果它不要求的存在。這將檢查$key,如果它存在,它會將其值設置爲$value。如果不存在,則會在文件末尾添加$key = $value。我還將該函數重命名爲與Power Shell命名約定更一致。

3

上述功能的更新版本具有一些參數化和詳細輸出(如果需要)。

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功能它是PowerShell的版本3。這是適應PowerShell的2版相同。

編輯:改變正則表達式固定在集-FileConfigurationValue兩個錯誤:

  1. 如果你有這樣一行:

    ; This is a Black line

    ,並嘗試做:

    Set-FileConfigurationValue $configFile "Black" 20 -ReplaceExistingValue

    您收到一條關於「替換」的消息,但沒有任何反應。

  2. 如果你有兩行這樣的:

    filesTmp = 50
    TMP = 50

    ,並嘗試做:

    Set-FileConfigurationValue $configFile "Tmp" 20 -ReplaceExistingValue

    你得到的兩行變!

    filesTmp = 20 TMP = 20

這是最後的版本:

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

我還添加了一個功能,從配置文件讀取

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

用法:

sed ".\*.config" "intranet-" "intranetsvcs-" 
相關問題