2013-03-27 48 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-" 
相关问题