Я пытаюсь Select-String
в тексте, который состоит из нескольких строк.
Пример:
"This is line1
<Test>Testing Line 2</Test>
<Test>Testing Line 3</Test>"
Я хочу иметь возможность выбрать все 3 строки в Select-String
. Однако, когда я делаю Select-String -Pattern "Line1"
, я выбираю только первую строку. Как я могу извлечь все 3 строки вместе?
Select-String -Pattern "Line1"
Select-String
позволяет выбрать заданное количество строк до или после совпадающей строки с помощью параметра -Context
. -Context 2,0
выбирает предыдущие 2 строки, -Context 0,2
выбирает последующие 2 строки, -Context 2,2
выбирает 2 строки до и 2 строки после совпадения.
Однако вы не получите строки совпадения и контекста в одном большом куске, поэтому вам нужно объединить совпадающую строку и контекст, если вы хотите, чтобы они были одной строкой:
Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
$($_.Line; $_.Context.PostContext) | Out-String
}
Как правильно указал @mklement0 в комментариях, приведенное выше выполняется сравнительно медленно, что не является проблемой, если вы обрабатываете только несколько совпадений, но становится проблемой, если вам нужно обработать сотни или тысячи совпадений. Для повышения производительности вы можете объединить значения в один массив и использовать оператор -join
:
Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
(,$_.Line + $_.Context.PostContext) -join [Environment]::NewLine
}
Обратите внимание, что два фрагмента кода не дают точно такой же результат, потому что Out-String
добавляет новую строку к каждой строке, включая последнюю, тогда как -join
помещает новые строки только между строк (не в конец последней). Однако каждый фрагмент можно изменить, чтобы получить тот же результат, что и другой. Обрежьте строки из первого примера, чтобы удалить завершающие символы новой строки, или добавьте еще одну новую строку к строкам из второго примера.
Если вы хотите вывести отдельные строки, просто выведите свойства Line
и PostContext
, не объединяя их в одну строку:
Select-String -Pattern 'Line1' -Context 0,2 | ForEach-Object {
$_.Line
$_.Context.PostContext
}
Select-String
работает со своими входными объектами индивидуально, и если вы либо передаете ему путь к файлу напрямую (через -Path
или -LiteralPath
), либо передаете вывод из Get-Content
, сопоставление выполняется для каждого линия.
Таким образом, передать ваш ввод как одну многострочную строку, который, если он исходит из файла, проще всего достигается с помощью Get-Content -Raw
(PSv3+):
Get-Content -Raw file.txt | Select-String -Pattern Line1
Обратите внимание, что это означает, что если соответствует шаблону, выводится файл весь контент доступен через свойство .Line
выходного объекта.
Напротив, если вы хотите сохранить построчное сопоставление, но также зафиксировать фиксированное количество окружающие линии, используйте параметр -Context
.
Get-Content file.txt | Select-String -Pattern Line1 -Context 0, 2
Полезный ответ Ансгара Вихерса показывает, как извлечь все строки из результата.
Также странные вещи происходят в подсказке по сравнению со сценарием. В приглашении select-string ищет \r
на концах строк необработанных строк в окнах, и возникает проблема вставки вкладок или вставки буквальных вкладок в приглашении.
Select-String operates on its input objects individually
это критическая точка!