Использование оператора -replace
с массивом входных строк позволяет получить краткое решение:
# Sample input lines (string array)
$lines = @'
blah_v1.2
foo_v1
vbarv_2.4
bar
'@ -split '\r?\n'
# Perform a regex-based string replacement on each input line,
# so as to only extract the substrings of interest.
$lines -replace '.*?v(.*)', '$1'
Выше приведены значения:
1.2
1
barv_2.4
bar
Дано массив в качестве LHS, -replace
воздействует на элементы массива один за другим.
Regex .*?v(.*)
не жадно (?
) соответствует чему-либо (.*
) вверхна сначала v
, затем (жадно) захватывает что-либо после v
в группе захвата ((...)
), $1
в операнде замены относится к этой группе захвата, и так какРегулярное выражение соответствует всей входной строке, вывод - это то, что пришло после первого v
на входе.
Обратите внимание, что -replace
пропускает ввод, который не соответствует регулярному выражению, как есть , поэтому bar
, который не содержит v
, также присутствует в выходных данных;если вы хотите опустить строки без v
, как в примере с вашим примером:
@($lines) -match 'v' -replace '.*?v(.*)', '$1'
Обратите внимание на @(...)
вокруг $lines
, чтогарантирует, что LHS всегда рассматривается как массив , поскольку -match
действует только как фильтр с массивом LHS, а не с одной входной строкой (см. ниже).
(Пример вводавыше по определению массив, но если вы загружаете свои строки из файла, например, с Get-Content
, однострочный входной файл приведет к одной строке , а не к массиву из 1 элемента.)
-match 'v'
, поэтому возвращает подмассив $line
элементов, которые содержат букву v
, с которой затем работает -replace
.
Примечание:
Подход массива + -replace
удобен и быстр для коллекций, которые уже находятся в памяти .
Тем не менее, если вы знаете, что ваш входной набор может вписаться в память в целом, вы можете улучшить производительность, захватив конвейерный (cmdlet) вывод в выражении ((...)
или, чтобы гарантироватьмассив, @(...)
), к которому можно снова применить -replace
:
@(Get-Content input.txt) -replace '.*?v(.*)', '$1'
Что касается то, что вы пытались :
С скаляром LHS, -match
возвращает Boolean (указывает, совпадает ли вход или нет), как вы уже видели.
Однако при использовании scalar LHS (только!) PowerShell заполняет автоматическую хеш-таблицу $Matches
подробной информацией о строке соответствия ((под), которая соответствует (запись 0
), значениях группы захвата (введите 1
для 1-й группы захвата, ...)), так что вы можете использовать это после , как показано в ответ Матиаса .