6

構成ファイルを変更する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 をファイルに追加できますか?
4

6 に答える 6

14

$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、ファイルに追加されます。

于 2013-03-27T16:33:38.027 に答える
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
         }

}

編集: 交換用のベルと不一致ホイッスルを追加しました。

于 2013-03-27T15:44:34.757 に答える
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 の命名規則との一貫性を高めました。

于 2013-03-27T15:52:38.893 に答える
0

@CarlR 関数は、PowerShell バージョン 3 用です。これは、PowerShell バージョン 2に適合したものと同じです。

編集: Set-FileConfigurationValue の 2 つのバグを修正するために正規表現を変更しました:

  1. 次のような 1 行がある場合:

    ; This is a Black line

    そして、あなたはやろうとします:

    Set-FileConfigurationValue $configFile "Black" 20 -ReplaceExistingValue

    「交換中」というメッセージが 1 つ表示されますが、何も起こりません。

  2. 次のような 2 行がある場合:

    filesTmp=50
    Tmp=50

    そして、あなたはやろうとします:

    Set-FileConfigurationValue $configFile "Tmp" 20 -ReplaceExistingValue

    2 つの行が変更されます。

    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
}  
于 2015-04-13T18:23:52.100 に答える
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-"
于 2016-10-26T19:44:26.590 に答える