Как получить захваченные группы из Select-String?
Я пытаюсь извлечь текст из набора файлов в Windows, используя Powershell (версия 4):
PS > Select-String -AllMatches -Pattern <mypattern-with(capture)> -Path file.jsp | Format-Table
Все идет нормально. Это дает хороший набор MatchInfo
объекты:
IgnoreCase LineNumber Line Filename Pattern Matches
---------- ---------- ---- -------- ------- -------
True 30 ... file.jsp ... {...}
Далее я вижу, что захваты находятся в матче участника, поэтому вынимаю их:
PS > Select-String -AllMatches -Pattern <mypattern-with(capture)> -Path file.jsp | ForEach-Object -MemberName Matches | Format-Table
Который дает:
Groups Success Captures Index Length Value
------ ------- -------- ----- ------ -----
{...} True {...} 49 47 ...
или как список с | Format-List
:
Groups : {matched text, captured group}
Success : True
Captures : {matched text}
Index : 39
Length : 33
Value : matched text
Здесь я останавливаюсь, я понятия не имею, как пойти дальше и получить список захваченных элементов группы.
Я пытался добавить еще | ForEach-Object -MemberName Groups
, но, похоже, возвращает то же самое, что и выше.
Самый близкий, который я получаю, с | Select-Object -Property Groups
что действительно дает мне то, что я ожидал (список наборов):
Groups
------
{matched text, captured group}
{matched text, captured group}
...
Но тогда я не могу извлечь захваченную группу из каждого из них, я попытался с | Select-Object -Index 1
Я получаю только один из этих наборов.
Обновление: возможное решение
Кажется, что, добавив | ForEach-Object { $_.Groups.Groups[1].Value }
Я получил то, что искал, но не понимаю, почему - поэтому я не уверен, что смогу получить правильный результат при распространении этого метода на целые наборы файлов.
Почему это работает?
Как примечание, это | ForEach-Object { $_.Groups[1].Value }
(т.е. без второго .Groups
) дает тот же результат.
Я хотел бы добавить, что при дальнейших попытках кажется, что команда может быть сокращена путем удаления | Select-Object -Property Groups
,
1 ответ
Посмотрите на следующее
$a = "http://192.168.3.114:8080/compierews/" | Select-String -Pattern '^http://(.*):8080/(.*)/$'
$a
сейчас MatchInfo
($a.gettype()
) оно содержит Matches
имущество.
PS ps:\> $a.Matches
Groups : {http://192.168.3.114:8080/compierews/, 192.168.3.114, compierews}
Success : True
Captures : {http://192.168.3.114:8080/compierews/}
Index : 0
Length : 37
Value : http://192.168.3.114:8080/compierews/
в группе участники вы найдете то, что вы ищете, так что вы можете написать:
"http://192.168.3.114:8080/compierews/" | Select-String -Pattern '^http://(.*):8080/(.*)/$' | % {"IP is $($_.matches.groups[1]) and path is $($_.matches.groups[2])"}
IP is 192.168.3.114 and path is compierews
Согласно документам PowerShell Регулярные выражения> Группы, захваты и замены:
При использовании -match
оператор, powershell создаст автоматическую переменную с именем$Matches
PS> "The last logged on user was CONTOSO\jsmith" -match "(.+was )(.+)"
Значение, возвращаемое из этого выражения, просто true
|false
, но PS добавит $Matches
хеш-таблица
Итак, если вы выведете $Matches
, вы получите все группы захвата:
PS> $Matches
Name Value
---- -----
2 CONTOSO\jsmith
1 The last logged on user was
0 The last logged on user was CONTOSO\jsmith
И вы можете получить доступ к каждой группе захвата индивидуально с помощью точечной записи, например:
PS> "The last logged on user was CONTOSO\jsmith" -match "(.+was )(.+)"
PS> $Matches.2
CONTOSO\jsmith
Дополнительные ресурсы:
- Чтобы получить несколько совпадений, см. Как захватить несколько совпадений регулярных выражений
- Чтобы передать параметры / флаги, см. Передача параметров регулярного выражения в PowerShell.
[regex]
тип
Поздний ответ, но для зацикливания нескольких совпадений и групп я использую:
$pattern = "Login:\s*([^\s]+)\s*Password:\s*([^\s]+)\s*"
$matches = [regex]::Matches($input_string, $pattern)
foreach ($match in $matches)
{
Write-Host $match.Groups[1].Value
Write-Host $match.Groups[2].Value
}
Это сработало в моей ситуации.
Используя файл: test.txt
// autogenerated by script
char VERSION[21] = "ABCDEFGHIJKLMNOPQRST";
char NUMBER[16] = "123456789012345";
Получите НОМЕР и ВЕРСИЮ из файла.
PS C:\> Select-String -Path test.txt -Pattern 'VERSION\[\d+\]\s=\s\"(.*)\"' | %{$_.Matches.Groups[
1].value}
ABCDEFGHIJKLMNOPQRST
PS C:\> Select-String -Path test.txt -Pattern 'NUMBER\[\d+\]\s=\s\"(.*)\"' | %{$_.Matches.Groups[1
].value}
123456789012345
Этот скрипт извлекает указанную группу захвата регулярного выражения из содержимого файла и выводит ее совпадения на консоль.
$file
это файл, который вы хотите загрузить$cg
это группа захвата, которую вы хотите захватить$regex
шаблон регулярного выражения
Пример файла и его содержимое для загрузки:
C: \ некоторые \file.txt
This is the especially special text in the file.
Пример использования: .\get_regex_capture.ps1 -file "C:\some\file.txt" -cg 1 -regex '\b(special\W\w+)'
Выход: special text
get_regex_capture.ps1
Param(
$file=$file,
[int]$cg=[int]$cg,
$regex=$regex
)
[int]$capture_group = $cg
$file_content = [string]::Join("`r`n", (Get-Content -Raw "$file"));
Select-String -InputObject $file_content -Pattern $regex -AllMatches | % { $_.Matches.Captures } | % { echo $_.Groups[$capture_group].Value }