web-dev-qa-db-ja.com

Select-Stringからキャプチャされたグループを取得する方法は?

Powershell(バージョン4)を使用して、Windows上の一連のファイルからテキストを抽出しようとしています。

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 }(つまり、2番目の.Groupsなし)は同じ結果になります。

それを追加したいのですが、さらに試行すると、パイプされた| Select-Object -Property Groupsを削除することでコマンドを短縮できるようです。

41
watery

以下をご覧ください

$a = "http://192.168.3.114:8080/compierews/" | Select-String -Pattern '^http://(.*):8080/(.*)/$' 

$aMatchInfo$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
45
JPBlanc

このスクリプトは、ファイルのコンテンツから正規表現の指定されたキャプチャグループを取得し、その一致をコンソールに出力します。


_$file_はロードするファイルです
_$cg_は、取得するキャプチャグループです。
_$regex_は正規表現パターンです



ロードするサンプルファイルとそのコンテンツ:

C:\ some\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 }
_
0