Shahar
Shahar

Reputation: 501

Creating an Array of my Custom objects Powershell

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

Answers (2)

Theo
Theo

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

Mathias R. Jessen
Mathias R. Jessen

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

Related Questions