Как выбрать многострочную строку? - PullRequest
1 голос
/ 27 марта 2019

Я пытаюсь 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"

Ответы [ 2 ]

1 голос
/ 27 марта 2019

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
}
0 голосов
/ 27 марта 2019

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

Полезный ответ Ansgar Wiechers показывает, как извлечь все строки из результата.

...