Управление текстовыми файлами: Как читать и редактировать с помощью PowerShell

Нужно знать, как использовать PowerShell для чтения текстового файла и замены текста? Это то, что мы называем чтением текстового файла PowerShell.

Не ищите дальше! Этот блоговый пост для вас. К концу поста я покажу вам функцию, которую я создал, чтобы сделать вашу жизнь намного проще.

Замена текста в файле с помощью PowerShell – это трехэтапный процесс.

  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'

Поиск и замена строки

Теперь, когда у нас есть содержимое файла в памяти в виде строки, нам нужно выполнить поиск и замену строки. Один из способов сделать это – использовать оператор -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'

Когда вы снова читаете файл C:\file.txt с помощью Get-Content, вы увидите, что теперь он содержит новое содержимое.

Работа с открытыми файловыми дескрипторами

Шаги, которые вы ранее выполнили, работают… в большинстве случаев. Однако в реальном мире вы обнаружите, что это не всегда бывает так.

Иногда вам придется иметь дело с файлами, которые открыты самим 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'
    
        Заменяет все вхождения строки 'water' на строку 'wine' в
        'C:\MyFile.txt'.
    .EXAMPLE
        PS> Find-InTextFile -FilePath 'C:\MyFile.txt' -Find 'water'
    
        Находит все вхождения строки 'water' в файле 'C:\MyFile.txt'.
    .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/