Reputation: 13
I have the following sample text that I'm trying to create a capture for.:
object-group network og-n-sna-EWB-UAT-srvrs-4
network-object host 10.34.68.108
network-object host 10.34.68.109
network-object host 10.34.68.110
object-group network og-n-bng-ind-users
network-object object obj-FAIBLR04L1025
network-object object obj-FAIBLR04L1741
network-object object obj-FAIBLR04L1344
network-object object obj-FAIBLR04L1193
network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
network-object host 10.36.50.101
network-object host 10.36.50.102
Now, I'm trying to figure out how to capture the name of the object group (og-n-bng-ind-users) that the object obj-FAIBLR04L1344 is a part of.
I've tried combining
*\snetwork-object\sobject\sobj-FAIBLR04L1344*
with a look behind, but I can't get it to work. Does anyone have any idea on how to construct this regular expression to work with PowerShell?
Upvotes: 0
Views: 90
Reputation: 61058
You could also opt to parse the whole file into an array of PSObjects, which not only makes it easy to get any item you seek, but it also allows you to save the file as CSV file to use in Excel for instance.
$result = switch -Regex -File 'D:\Test\thefile.txt' {
'^object-group network ' { $group = ($_.Trim() -split '\s')[-1] }
'network-object' {
$item = $_.Trim() -split '\s'
[PsCustomObject]@{
Group = $group
Type = $item[1]
Value = $item[2]
}
}
}
Once you have this file converted to an object array, you can get anything you need from it, like the object group name for Value 'obj-FAIBLR04L1344'
($result | Where-Object { $_.Value -eq 'obj-FAIBLR04L1344' }).Group # --> og-n-bng-ind-users
Upvotes: 0
Reputation: 8868
Another way is to use ConvertFrom-String. This works on your small sample data. It's quite possible there needs to be more "training" data for the template. The technology it's built on is amazing.
$template = @'
object-group network og-n-sna-EWB-UAT-srvrs-4
network-object host 10.34.68.108
network-object host 10.34.68.109
network-object host 10.34.68.110
object-group network {Name: og-n-bng-ind-users}
network-object object obj-FAIBLR04L1025
network-object object obj-FAIBLR04L1741
network-object object obj-FAIBLR04L1344
network-object object obj-FAIBLR04L1193
network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
network-object host 10.36.50.101
network-object host 10.36.50.102
'@
@'
object-group network og-n-sna-EWB-UAT-srvrs-4
network-object host 10.34.68.108
network-object host 10.34.68.109
network-object host 10.34.68.110
object-group network og-n-bng-ind-users
network-object object obj-FAIBLR04L1025
network-object object obj-FAIBLR04L1741
network-object object obj-FAIBLR04L1344
network-object object obj-FAIBLR04L1193
network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
network-object host 10.36.50.101
network-object host 10.36.50.102
'@ | ConvertFrom-String -TemplateContent $template
Or from a file
Get-Content $file | ConvertFrom-String -TemplateContent $template
Name
----
og-n-bng-ind-users
Upvotes: 0
Reputation: 4099
Assuming the text is stored in text.txt
, I believe this could work:
Get-Content -Raw text.txt |
Select-String `
-AllMatches `
-Pattern '(?<=object-group network ).+(?=(\s*network-object object .*)*\s*network-object object obj-FAIBLR04L1344)' |
foreach {$_.Matches.Value}
Get-Content -Raw
passes the content of text.txt
as a single object (multiline string) to Select-String
. The -AllMatches
option shows all the matches instead of just the first one (in case the object is in several groups in your example text). The -Pattern
option receives the pattern to search. This pattern uses a lookbehind for object-group network
and a lookahead for zero or more \s*network-object object .*
followed by \s*network-object object obj-FAIBLR04L1344
.
Select-String
prints matching lines (the whole text in this case). To avoid this, foreach {$_.Matches.Value}
iterates on the matches and prints its value.
Upvotes: 1
Reputation: 4634
Are you sure you want RegEx here?
Prepare:
$text = @'
object-group network og-n-sna-EWB-UAT-srvrs-4
network-object host 10.34.68.108
network-object host 10.34.68.109
network-object host 10.34.68.110
object-group network og-n-bng-ind-users
network-object object obj-FAIBLR04L1025
network-object object obj-FAIBLR04L1741
network-object object obj-FAIBLR04L1344
network-object object obj-FAIBLR04L1193
network-object object obj-FAIBLR06L1318
object-group network og-n-mdm-srvrs-7
network-object host 10.36.50.101
network-object host 10.36.50.102
'@
$networkObjectId = 'obj-FAIBLR04L1344' + [System.Environment]::NewLine
Variant:
$objectGroupListFound = @($text.Split([string[]]@('object-group'), [System.StringSplitOptions]::RemoveEmptyEntries) |
Where-Object { $_.Contains( "network-object object $($networkObjectId)" ) } |
ForEach-Object { $_.Split([System.Environment]::NewLine)[0]} |
ForEach-Object { $_.Split()[-1]} )
if ($objectGroupListFound.Count -ne 1)
{
Write-Error "No objectGroup found for networkObjectId $($networkObjectId) or found more than one. Found $($objectGroupListFound.Count)."
}
## There I omit "else", assuming code upper is wrapped into try block and on error, it will not reach this line.
$objectGroup = $objectGroupListFound[0]
Variant:
$tempText = $text.Substring(0,$text.IndexOf($networkObjectId))
$tempText = $tempText.Substring($tempText.LastIndexOf('object-group'))
$objectGroup = $tempText.Split("`r`n".ToCharArray(), [System.StringSplitOptions]::RemoveEmptyEntries)[0].Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)[2]
Variant (line by line) - I think it is most simple and clear
$text = [System.IO.File]::ReadAllLines($path)
# or $text = $text.Split([char[]]"`r`n", [System.StringSplitOptions]::RemoveEmptyEntries)
$networkObjectId = "obj-FAIBLR04L1344"
$objectGroupCache = $null
$objectGroup = $null
for ($i = 0; $i -lt $text.Count; $i++)
{
if ($text[$i].Trim().StartsWith('object-group network'))
{
# We are entering this group.
$objectGroupCache =$text[$i].Split([char[]]" `t", [System.StringSplitOptions]::RemoveEmptyEntries)[-1]
}
elseif ($text[$i].Trim().StartsWith('network-object') -and $text[$i].Trim().EndsWith($networkObjectId))
{
$objectGroup = $objectGroupCache
break;
}
}
if ([String]::IsNullOrWhiteSpace($objectGroup))
{
Write-Error "Not found"
}
Upvotes: 0