Regex's are a language all their own. Yours looks to work okay on the limited data you offered to test it with. If this were a Perl forum I wouldn't offer this opinion, but this is PowerShell and there are many people that read this forum that do not understand regex. You may also find that any code you write that uses a complex regex will befuddle someone that has to maintain your code (and it may befuddle you, too, years from now). For a complex regex it might be beneficial to use the "#" option to document what's going on in the regex.
Another (simpler) approach might be to extract two groups from the string. The first would be "PTP" and the next would be everything within the parentheses. Split the 2nd group on the commas. Then split the 1st result of the split on the ":". Most people understand string manipulation far better than regular expressions.
All of the above is just my opinion. Your code works.
Here's an expansion of your code to produce a PowerShell object that holds the name/value pairs of the named groups in a way that allows you to do any further work on it using a CSV (if you choose to export the output in that format).
$log = "sthg... 0.003789567 PTP(10.156.210.14:12,unicast,telecom) -0.001123234",
"sthg... 0.003789567 PTP(10.156.210.15:12,multicast,telecom) -0.001123234"
[regex]$test = '(?<protocol>PTP)\((?<IP>(\d{1,3}(\.)?){4}(?=:)):\d+\,(?<type>(?<=\,).*(?=\,))'
$h = [ordered]@{}
$namefound = $false
$log |
ForEach-Object {
ForEach ($group in $test.Matches($_).groups) {
if ($group.name -match '\D+') {
$namefound = $true
$h[$group.Name] = $group.Value
}
}
if ($namefound) {
[PSCustomObject]$h
$namefound = $false
$h.Clear()
}
}