Применить фильтр регулярных выражений для строки, которая возвращает значение после появления данного символа в powershell - PullRequest
0 голосов
/ 19 декабря 2018

Я хочу создать сценарий PowerShell, который возвращает фразу после первого вхождения данного символа в строку.Например, я хочу получить все фразы после первого появления символа v:

blah_v1.2
foo_v1
vbarv_2.4
bar

Результат будет

1.2
1
barv_2.4

Я пытался создать что-то подобное, но $ FooVersion возвращает логическое значение вместо строки.

$Foo = "blah_v1.1"
$FooVersion = $Foo -match "_v (.*)"

Write-Host $Foo
Write-Host $FooVersion

Есть идеи?Приветствия

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Попробуйте некоторые возможности:

$Foo = "blah_v1.1"

# using -replace
# returns a string without 'v' as-is
$FooVersion = $Foo -replace '(?:[^v]*v)(.*)', '$1'

или

# using -split at the first 'v' character
# returns a string without 'v' as-is; use [1] to return '' instead
$FooVersion = ($Foo -split 'v', 2)[-1]

или

# using -match
# returns $null for a string without 'v'; add `else { $Foo }` to return it as-is
$FooVersion = if ($Foo -match 'v(.*)') { $Matches[1] }

Write-Host $Foo
Write-Host $FooVersion
0 голосов
/ 19 декабря 2018

Использование оператора -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-й группы захвата, ...)), так что вы можете использовать это после , как показано в ответ Матиаса .

0 голосов
/ 19 декабря 2018

Убедитесь, что вы ищете все, что не является v, а затем первым v, а затем извлекаете захваченное значение из переменной $Matches:

$strings = -split @'
blah_v1.2
foo_v1
vbarv_2.4
bar
'@

$strings |ForEach-Object {
    if($_ -match '[^v]*v(.*)'){
        $Matches[1]
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...