テキストファイルの管理: PowerShellでの読み取りと編集方法

テキストファイルを読み込み、テキストを置換するためにPowerShellを使用する方法を知りたいですか?これをPowerShell Read-Text Fileと呼んでいます。

これ以上探す必要はありません!このブログ記事がお役に立ちます。記事の最後に、あなたの生活をかなり楽にするために作成した関数を紹介します。

テキストファイル内のテキストを置換するには、PowerShellを使用することができます。これは3つのステップで行います。

  1. ファイルの読み込み
  2. 文字列の検索と置換
  3. 変更をファイルに書き込む

ファイルの読み込み

まず最初にファイルを読み込む必要があります。まず、Set-Contentコマンドレットを使用してファイルを作成しましょう。

Set-Content -Path 'C:\file.txt' -Value 'foo bar baz'

このファイルを読み込むには、Get-Contentコマンドを使用します。以下のように、Pathパラメータにテキストファイルのパスを指定してファイルを読み込むことができます。

$content = Get-Content -Path 'C:\file.txt'

文字列の検索と置換

これで、ファイルの内容をメモリ内の文字列として持っているので、文字列を検索して置換する必要があります。その方法の1つは、-replace演算子を使用する方法です。このPowerShellの演算子は、文字列を検索して別の文字列で置き換えます。

例のファイルの内容を使用して、検索文字列にfoo、置換文字列にbarを指定すると、ファイルの内容はfoo foo bazになります。

PS> $newContent = $content -replace 'foo', 'bar'
bar bar baz

ファイルへの書き込み

新しいファイルの内容が$newContentに保存されたので、この新しい内容をファイルに書き込む必要があります。その方法の一つは、Set-Contentコマンドを使用することです。

Set-Contentコマンドは、ファイルのすべての内容を新しい値に置き換えます。

$newContent | Set-Content -Path 'C:\file.txt'

このようにGet-ContentC:\file.txtファイルを読み込むと、新しい内容が含まれていることがわかります。

開いたファイルハンドルの取り扱い

以前に行った手順は…ほとんどの場合には機能します。しかし、実際の世界では常にうまくいかないことがあります。

時々、PowerShell自体で開かれているファイルに対処しなければならないことがあることに気付くでしょう。これにより、新しい内容をファイルに書き込むことができません。

この開いたファイルハンドルの状況を解消するために、新しい内容を一時的なテキストファイルに最初に作成し、元のファイルを削除してから一時ファイルの名前を変更する簡単なワークフローを作成しました。

以下にその動作例を示します。

$filePath = 'C:\file.txt'
$tempFilePath = "$env:TEMP\$($filePath | Split-Path -Leaf)"
$find = 'foo'
$replace = 'bar'

(Get-Content -Path $filePath) -replace $find, $replace | Add-Content -Path $tempFilePath

Remove-Item -Path $filePath
Move-Item -Path $tempFilePath -Destination $filePath

以下は、このアプローチとファイル内のテキストを検索(置換ではない)する機能Find-InTextFileの例です。

この関数は、より強力な正規表現構文を使用して文字列を検索することも可能です。正規表現を使用すると、シングルクォート、特殊文字などの特殊文字を使用した柔軟な検索が可能になります。

また、下記のようにforeachループを使用して複数のファイルを一度に処理しています。これは、複数のファイルを処理する場合に便利です。

function Find-InTextFile {
    <#
    .SYNOPSIS
        テキストファイルまたは複数のファイル内の文字列を検索(または置換)します。
    .EXAMPLE
        PS> Find-InTextFile -FilePath 'C:\MyFile.txt' -Find 'water' -Replace 'wine'
    
        'C:\MyFile.txt' のすべてのインスタンスで文字列 'water' を文字列 'wine' に置換します。
    .EXAMPLE
        PS> Find-InTextFile -FilePath 'C:\MyFile.txt' -Find 'water'
    
        ファイル 'C:\MyFile.txt' のすべてのインスタンスで文字列 'water' を検索します。
    .PARAMETER FilePath
        検索/置換を行いたいテキストファイルのファイルパスです。
    .PARAMETER Find
        置換したい文字列です。
    .PARAMETER Replace
        'Find' 文字列を置換する文字列です。
    .PARAMETER NewFilePath
        既存のファイルの内容を置換する代わりに、置換された新しいファイルを作成する場合は、このパラメータを使用します。
    .PARAMETER Force
        NewFilePath パラメータが使用されている場合、このパラメータを使用して NewFilePath に存在するファイルを上書きします。
    #>
    [CmdletBinding(DefaultParameterSetName = 'NewFile')]
    [OutputType()]
    param (
        [Parameter(Mandatory = $true)]
        [ValidateScript({Test-Path -Path $_ -PathType 'Leaf'})]
        [string[]]$FilePath,
        [Parameter(Mandatory = $true)]
        [string]$Find,
        [Parameter()]
        [string]$Replace,
        [Parameter(ParameterSetName = 'NewFile')]
        [ValidateScript({ Test-Path -Path ($_ | Split-Path -Parent) -PathType 'Container' })]
        [string]$NewFilePath,
        [Parameter(ParameterSetName = 'NewFile')]
        [switch]$Force
    )
    begin {
        $Find = [regex]::Escape($Find)
    }
    process {
        try {
            foreach ($File in $FilePath) {
                if ($Replace) {
                    if ($NewFilePath) {
                        if ((Test-Path -Path $NewFilePath -PathType 'Leaf') -and $Force.IsPresent) {
                            Remove-Item -Path $NewFilePath -Force
                            (Get-Content $File) -replace $Find, $Replace | Add-Content -Path $NewFilePath -Force
                        } elseif ((Test-Path -Path $NewFilePath -PathType 'Leaf') -and !$Force.IsPresent) {
                            Write-Warning "The file at '$NewFilePath' already exists and the -Force param was not used"
                        } else {
                            (Get-Content $File) -replace $Find, $Replace | Add-Content -Path $NewFilePath -Force
                        }
                    } else {
                        (Get-Content $File) -replace $Find, $Replace | Add-Content -Path "$File.tmp" -Force
                        Remove-Item -Path $File
                        Move-Item -Path "$File.tmp" -Destination $File
                    }
                } else {
                    Select-String -Path $File -Pattern $Find
                }
            }
        } catch {
            Write-Error $_.Exception.Message
        }
    }
}

リソース

Set-Contentコマンドの詳細については、Set-Content: PowerShellでファイルに書き込む方法を参照してください。また、ファイルに内容を書き込む別の方法として、Out-Fileコマンドもあります。

Source:
https://adamtheautomator.com/powershell-read-text-file/