3

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

0

2 Answers 2

3

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…}
Sign up to request clarification or add additional context in comments.

3 Comments

$obj |Add-Member ... -> can i use this line to add property IP with value and Property with array of port numbers?
It's just an example, replace with any number of Add-Member calls you need
@Shahar Updated the answer to show an easier way of creating the new objects (although this will not work with PowerShell 2.0, only 3.0 and newer)
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.