Как остановить Get-Content -wit после того, как я найду определенную строку в текстовом файле, используя powershell?

Я использую этот скрипт ниже в Powershell (версия 5.1):

Get-Content -Path path\to\text\file\to\be\read.txt -Wait

Теперь это продолжает читать даже после того, как файл не получает обновления. Как я могу остановиться после того, как найду определенную строку в текстовом файле? Есть ли другой способ остановить это при условии?

1 ответ

Решение

Вы можете передать вывод и использовать foreach для проверки каждой строки, если строка равна определенной строке, которую вы можете использовать break остановить команду:

Get-Content path\to\text\file\to\be\read.txt -wait | % {$_ ; if($_ -eq "yourkeyword") {break}}

Например, если вы запустите команду выше и сделаете следующее в другой оболочке:

"yourkeyword" | Out-File path\to\text\file\to\be\read.txt -Append

Get-Content отображает новую строку и останавливается.


Объяснение:

| % - строка foreach, которая находится в файле или добавляется в файл во время выполнения функции

$_; - сначала выписать строку foreach, затем выполнить другую команду

if($_ -eq "yourkeyword") {break} - если строка foreach равна желаемому ключевому слову / строке, остановите Get-Content

tl;dr

do {
  Get-Content -Path path\to\text\file\to\be\read.txt -Wait | ForEach-Object {
    # Pass the input line through.
    $_
    # Exit once the string of interest is found.
    if ($_ -match 'patternOfInterest') { break } 
  }
} while ($false) # dummy loop so that `break` can be used.

# NOTE: Without the dummy `do` loop, this code would not be reached.
'Line of interest found.'

Обратите внимание, что -matchОператор выполняет сопоставление подстроки с помощью регулярных выражений ( about_Regular_Expressions).

Читайте, почему манекен do петля нужна.


Ответ Paxz на правильном пути, но он пытается использоватьbreak(изолированно) для выхода из конвейера, который (обычно) завершает весь сценарий (если вы отправляете конвейер как одну команду в интерактивном режиме, вы можете не заметить).

break / continueпредназначены для выхода / продолжения циклов (for, foreach, do, while, а также switchзаявления [1]), а не конвейеры.

В PowerShell [Core] 7.0 нет прямого способа преждевременно выйти из конвейера, хотя добавление этой функции является предметом этого давнего запроса на функцию на GitHub; в настоящее время только прямое использованиеSelect-Object с участием -Firstможет преждевременно выйти из конвейера из-за использования закрытого исключения; покаreturn может использоваться в ForEach-Object блок сценария, он только завершает вызов текущего блока сценария, продолжая обрабатывать дополнительный ввод конвейера.

Если вы используете break или continue, PowerShell будет искать любой закрывающий цикл, и если его нет, скрипт завершит работу.

Однако, если вы обернете свой конвейер [2]фиктивным циклом, как показано выше, единственная цель которого - предоставить что-то дляbreakвырваться из - исполнение продолжается, как (обычно) желательно.

Предупреждение:

break / continue (а также throw) имеют важный побочный эффект: они не дают другим командам, участвующим в конвейере, нормально завершиться; то есть ихend блоки / EndProcessing()методы не вызываются, что может быть проблематичным по двум причинам:

  • Командлеты, которым необходимо очистить (удалить) временно заблокированные ресурсы , не могут быть очищены.

  • Командлеты агрегирования - те, которые по необходимости собирают весь ввод, прежде чем смогут произвести вывод, - никогда не производят вывод; вот простой пример:

PS> do { 5..1 | % { $_; if ($_ -eq 3) { break } } | Sort-Object } while ($false)
# !! NO OUTPUT, because Sort-Object's EndProcessing() method was never called.

[1] Когда вы исследуете одно значение с switch заявление, breakвыходит из оператора, как и следовало ожидать. Если обрабатывается массив (набор) значений,breakтакже немедленно выходит из оператора, не обрабатывая дальнейшие элементы в массиве;continue, напротив, продолжает обработку следующего элемента.

[2] Другой вариант - использовать throw для генерации ошибки завершения сценария, которую вы поймаете, заключив конвейер в try / catchзаявление, как показано в этом ответе. Однако это имеет побочный эффект записи записи в автоматическом$Errorколлекции, даже если концептуально реальной ошибки не произошло.

Другие вопросы по тегам