Reputation: 501
I have a data file which contains TXT. im building a Function to iterate through that data file and Build Custom objects according. and the end of it, i want the function to return an array of these custom objects. here is an example of one object and how it suppose look:
$NmapOBJ1 = New-Object PSObject
$NmapOBJ1 | Add-Member -type NoteProperty -name "IP" -Value "192.168.10.10"
$ports = @(22,80,435)
$NmapOBJ1 | Add-Member -type NoteProperty -name "Ports" -Value $ports
Each object has IP and Ports available, Now im creating a loop and i want a var like $k=0 which will get $k++ each time loops re-run. so one time $NmapOBJ1 will be built and then $NmapOBJ2, $NmapOBJ3.. but i cannot use :
$k=0
$NmapOBJ$k = New-Object PSObject
Because i will get error : Unexpected token '$k' in expression or statement. Thanks in advance
***EDIT *** Example of txt file can be:
Nmap scan report for 11.1.1.11
21/tcp filtered ftp
49/tcp filtered tacacs
67/tcp open tcpwrapped
111/tcp filtered rpcbind
121/tcp filtered rpcbind
123/tcp filtered ntp
179/tcp filtered bgp
646/tcp filtered ldp
Nmap scan report for 2.2.22.2
21/tcp filtered ftp
67/tcp open tcpwrapped
111/tcp filtered rpcbind
123/tcp filtered ntp
179/tcp filtered bgp
646/tcp filtered ldp
33012/tcp filtered unknown
I would then want an object1.ip = 11.1.1.11; object1.ports = @(21,49,67,111,121,123,179,646)
and so on..
Upvotes: 3
Views: 6022
Reputation: 61253
Instead of trying to create new variables, you'd be better of getting an array of PSObjects from that file.
Something like this should work:
# read the text file as single string and split it into n textblocks. Remove empty blocks
$result = (Get-Content -Path 'D:\Test\NmapScanReport.txt' -Raw) -split 'Nmap.+for\s*' |
Where-Object { $_ -match '\S'} |
ForEach-Object {
# split each textblock into separate lines
$lines = $_ -split '\r?\n'
# and output an object with properties IP and Ports (the latter is an array)
[PsCustomObject]@{
IP = $lines[0].Trim()
Ports = for ($i = 1; $i -lt $lines.Count; $i++) { ($lines[$i] -split '/')[0] }
}
}
# output on screen
$result
# write to csv file
$result | Export-Csv -Path 'D:\Test\IpAndPorts.csv' -NoTypeInformation
Output on screen:
IP Ports -- ----- 11.1.1.11 {21, 49, 67, 111...} 2.2.22.2 {21, 67, 111, 123...}
Upvotes: 2
Reputation: 175085
As you've found $NMapObj$k
doesn't work - PowerShell's variable reference syntax doesn't support variable variables (like in PHP for examples)
I'd suggest using a list to collect the objects:
$listOfObjects = New-Object 'System.Collections.Generic.List[psobject]'
$obj = New-Object psobject
$obj |Add-Member ...
$listOfObjects.Add($obj)
Then at the end of your function:
return $listOfObjects
PowerShell will then enumerate the list and the assignment target will receive an array of the objects in the list
The more PowerShell-idiomatic solution here is to just emit each custom object as you go!
For the input sample you've shown, you can write a simple parser with a switch
statement like this:
function Parse-NMapReport
{
param(
[string]$Path
)
$IP = ""
switch -File $path -Regex {
'Nmap scan report for (?<ip>[\d\.]+)' {
if($IP){
# Defining the object without assigning it to anything
# This will make the object "bubble up" back to the caller
[PSCustomObject]@{
IP = $IP
Ports = $Ports
}
}
$IP = $Matches['ip']
$Ports = @()
}
'^(?<port>\d+)/tcp' {
$Ports += ($Matches['port'] -as [int])
}
}
if($IP){
[PSCustomObject]@{
IP = $IP
Ports = $Ports
}
}
}
Now you can do:
PS C:\> $results = Parse-NMapReport -Path ".\Path\to\nmap.txt"
And $results
will be an array of the custom objects created:
PS C:\> $results
IP Ports
-- -----
11.1.1.11 {21, 49, 67, 111…}
2.2.22.2 {21, 67, 111, 123…}
Upvotes: 3