PowerShell: Set-Konten mengalami masalah dengan file yang sudah digunakan

Saya sedang mengerjakan skrip PowerShell yang menemukan semua file dengan POLA dalam DIREKTORI tertentu, mencetak baris dokumen yang relevan dengan POLA yang disorot, dan kemudian mengganti POLA dengan kata REPLACE yang disediakan, lalu menyimpan file kembali. Jadi itu benar-benar mengedit file.

Kecuali saya tidak bisa mengubah file tersebut, karena Windows mengeluh tentang file tersebut sudah terbuka. Saya mencoba beberapa metode untuk mengatasi ini, tetapi tetap mengalami masalah. Mungkin ada yang bisa membantu:

param(
    [string] $pattern = ""
    ,[string] $replace = ""
    ,[string] $directory ="."
    ,[switch] $recurse = $false
    ,[switch] $caseSensitive = $false)

if($pattern -eq $null -or $pattern -eq "")
{
    Write-Error "Please provide a search pattern." ; return
}

if($directory -eq $null -or $directory -eq "")
{
    Write-Error "Please provide a directory." ; return
}

if($replace -eq $null -or $replace -eq "")
{
    Write-Error "Please provide a string to replace." ; return
}

$regexPattern = $pattern
if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern" }
$regex = New-Object System.Text.RegularExpressions.Regex $regexPattern

function Write-HostAndHighlightPattern([string] $inputText)
{
    $index = 0
    $length = $inputText.Length
    while($index -lt $length)
    {
        $match = $regex.Match($inputText, $index)
        if($match.Success -and $match.Length -gt 0)
        {
            Write-Host $inputText.SubString($index, $match.Index) -nonewline
            Write-Host $match.Value.ToString() -ForegroundColor Red -nonewline
            $index = $match.Index + $match.Length
        }
        else
        {
            Write-Host $inputText.SubString($index) -nonewline
            $index = $inputText.Length
        }
    }
}

Get-ChildItem $directory -recurse:$recurse |
    Select-String -caseSensitive:$caseSensitive -pattern:$pattern |    
    foreach {
        $file = ($directory + $_.FileName)
        Write-Host "$($_.FileName)($($_.LineNumber)): " -nonewline
        Write-HostAndHighlightPattern $_.Line
        %{ Set-Content $file ((Get-Content $file) -replace ([Regex]::Escape("[$pattern]")),"[$replace]")}
        Write-Host "`n"
        Write-Host "Processed: $($file)"
    }

Masalahnya terletak di blok kode terakhir, tepat di panggilan Get-ChildItem. Tentu saja, beberapa kode di blok itu sekarang agak rusak karena saya mencoba memperbaiki masalah lalu berhenti, namun perlu diingat maksud dari bagian skrip tersebut. Saya ingin mendapatkan kontennya, mengganti kata-katanya, lalu menyimpan teks yang diubah kembali ke file tempat saya mendapatkannya.

Bantuan apa pun akan sangat dihargai.


person Eli Wilson    schedule 20.04.2012    source sumber


Jawaban (3)


Menghapus jawaban saya sebelumnya, menggantinya dengan ini:

Get-ChildItem $directory -recurse:$recurse
foreach {        
    $file = ($directory + $_.FileName)

    (Get-Content $file) | Foreach-object {
        $_ -replace ([Regex]::Escape("[$pattern]")),"[$replace]")
    } | Set-Content $file
}

Catatan:

  • Tanda kurung di sekitar Get-Content untuk memastikan file diambil sekaligus (dan karenanya ditutup).
  • Perpipaan ke perintah selanjutnya, bukan inlining.
  • Beberapa perintah Anda telah dihapus untuk memastikan ini adalah pengujian sederhana.
person yamen    schedule 20.04.2012
comment
Itu terus memberi saya kesalahan terkait dengan jumlah tanda kurung, tetapi berapa pun jumlah tanda kurung yang dipindahkan adalah sia-sia. Namun, saya lebih menyukainya dan pasti akan menggunakannya, tentunya dengan beberapa modifikasi. Terima kasih banyak. Saya masih belum membuat skripnya berfungsi sepenuhnya, tetapi saya rasa dengan semua modifikasi ini, saya semakin dekat. - person Eli Wilson; 21.04.2012
comment
Tanda kurung di sekitar Get-Content adalah kuncinya bagi saya - person Pete Baughman; 30.04.2015

Sekadar saran tetapi Anda dapat mencoba melihat dokumentasi untuk blok kode parameter. Ada cara yang lebih efisien untuk memastikan bahwa parameter dimasukkan jika Anda memerlukannya dan menampilkan pesan kesalahan jika pengguna tidak memasukkannya.

Tentang_throw: http://technet.microsoft.com/en-us/library/dd819510.aspx Tentang_functions_advanced_parameters: http://technet.microsoft.com/en-us/library/dd347600.aspx

Lalu tentang penggunaan Write-Host sepanjang waktu: http://powershell.com/cs/blogs/donjones/archive/2012/04/06/2012-scripting-games-commentary-stop-using-write-host.aspx

person Community    schedule 20.04.2012

Baiklah, saya akhirnya duduk dan mengetik semuanya secara berurutan di PowerShell, lalu menggunakannya untuk membuat skrip saya.

Sebenarnya sangat sederhana;

$items = Get-ChildItem $directory -recurse:$recurse
$items |
foreach {
    $file = $_.FullName
    $content = get-content $file
    $newContent = $content -replace $pattern, $replace
    Set-Content $file $newcontent
}

Terima kasiih atas semua bantuan kalian.

person Eli Wilson    schedule 22.04.2012