5

指定されたディレクトリ内のPATTERNを含むすべてのファイルを検索し、PATTERNを強調表示してドキュメントの関連行を印刷し、PATTERNを指定されたREPLACE単語に置き換えて、ファイルを保存するPowerShellスクリプトに取り組んでいます。したがって、実際にファイルを編集します。

Windowsがファイルがすでに開いていることについて文句を言うので、ファイルを変更するためにそれを取得できないことを除いて。私はこれを解決するためにいくつかの方法を試しましたが、問題にぶつかり続けます。おそらく誰かが助けることができます:

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

この問題は、コードの最後のブロック内のGet-ChildItem呼び出しで発生します。もちろん、そのブロック内のコードの一部は、問題を修正して停止しようとしたために少し混乱していますが、スクリプトのその部分の意図を覚えておいてください。コンテンツを取得し、単語を置き換えてから、変更したテキストを取得したファイルに保存します。

どんな助けでも大歓迎です。

4

3 に答える 3

6

以前の回答を削除し、次のように置き換えました。

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

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

ノート:

  • Get-Contentファイルが一度に丸呑みされる(したがって閉じられる)ことを保証するための括弧。
  • インライン化ではなく、後続のコマンドへのパイプ。
  • 簡単なテストであることを確認するために、コマンドの一部が削除されています。
于 2012-04-20T06:08:36.640 に答える
0

よし、ようやく腰を下ろして、すべてを PowerShell に順番に入力し、それを使用してスクリプトを作成しました。

実際にはとても簡単でした。

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

助けてくれてありがとう。

于 2012-04-22T18:52:42.197 に答える
0

単なる提案ですが、パラメーター コード ブロックのドキュメントを参照してみてください。パラメーターが必要な場合は確実に入力され、ユーザーが入力しない場合はエラー メッセージをスローする、より効率的な方法があります。

About_throw: http://technet.microsoft.com/en-us/library/dd819510.aspx About_functions_advanced_pa​​rameters: http://technet.microsoft.com/en-us/library/dd347600.aspx

そして、常に Write-Host を使用することについて: http://powershell.com/cs/blogs/donjones/archive/2012/04/06/2012-scripting-games-commentary-stop-using-write-host.aspx

于 2012-04-20T05:01:39.893 に答える