1. ホーム
  2. regex

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

2023-06-11 19:22:13

質問

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                      ...                           {...}

次に、キャプチャがmatchesメンバーに入っているのがわかるので、それを取り出します。

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 .

どのように解決するのですか?

下記をご覧ください。

$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