2013-03-27 30 views
5

Tôi đang làm việc trên tập lệnh PowerShell để sửa đổi các tệp cấu hình. Tôi có file như thế này:Chức năng Powershell để thay thế hoặc thêm dòng trong các tập tin văn bản

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

ai sẽ trông như thế này:

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

Nếu có một bộ chìa khóa (Logentrytimeout), chỉ cần cập nhật nó với giá trị nhất định. Bỏ qua các nhận xét, trong đó khóa được đề cập (các dòng bắt đầu bằng #). Khóa không phân biệt chữ hoa chữ thường.

Nếu khóa không được đặt (disablepostprocessing và segmentstarttimeout), hãy thêm khóa và giá trị vào tệp. chức năng của tôi cho đến nay đi như thế này:

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" 
  • regex đúng là gì?
  • Làm cách nào để kiểm tra xem có thay thế không?
  • Nếu không có thay thế: Làm thế nào tôi có thể nối thêm $ + "=" + $ giá trị vào tệp?

Trả lời

13

Giả sử $key bạn muốn thay thế luôn luôn ở đầu dòng, và rằng nó không chứa ký tự đặc biệt regex

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" 

Nếu không có sự thay thế $key = $value sẽ được nối thêm vào các tập tin.

2

Tôi muốn làm điều này:

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: thêm một cái chuông thay thế, và không phù hợp với tiếng còi.

1

Thay đổi chức năng này:

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

Sau đó, khi bạn gọi hàm, sử dụng định dạng này:

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

Edit: Tôi quên yêu cầu của bạn thêm dòng nếu nó không hiện hữu. Điều này sẽ kiểm tra số $key, nếu tồn tại, giá trị này sẽ đặt giá trị là $value. Nếu không tồn tại, nó sẽ thêm $key = $value vào cuối tệp. Tôi cũng đã đổi tên chức năng để phù hợp hơn với quy ước đặt tên vỏ điện.

3

Phiên bản cập nhật của các chức năng ở trên với một số thông số kỹ thuật và đầu ra tiết nếu được yêu cầu.

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 Chức năng đó là cho PowerShell Version 3. Đây nó giống thích nghi với PowerShell Phiên bản 2.

EDIT: Thay đổi biểu thức chính quy để sửa hai lỗi trên Set-FileConfigurationValue:

  1. Nếu bạn có một dòng như thế này:

    ; This is a Black line

    Và bạn cố gắng làm:

    Set-FileConfigurationValue $configFile "Black" 20 -ReplaceExistingValue

    Bạn nhận được một thông báo về "Thay thế" nhưng không có gì xảy ra.

  2. Nếu bạn có hai dòng như thế này:

    filesTmp = 50
    Tmp = 50

    Và bạn cố gắng làm:

    Set-FileConfigurationValue $configFile "Tmp" 20 -ReplaceExistingValue

    Bạn được hai dòng thay đổi !

    filesTmp = 20 Tmp = 20

Đây là phiên bản cuối cùng:

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

Tôi cũng đã thêm một chức năng để đọc từ tập tin cấu hình

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

Cách sử dụng:

sed ".\*.config" "intranet-" "intranetsvcs-" 
Các vấn đề liên quan