selecting IP from a specific line

YaroC 316 Reputation points
2020-10-16T12:30:28.163+00:00

I'm looking for a way of extracting IP address for a time server which is kept in my results variable that also holds multiple other unrelated IPs. The line holding the IP I'm interested in is in format
source type: NTP(xx.xx.xx.xx:port,unicast)
The source type pattern shows up multiple times but at least this part is easy as it's always the first occurrence. How would I get just the NTP and IP address skipping all the rest from the example line?

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,628 questions
0 comments No comments
{count} votes

Accepted answer
  1. Rich Matheisen 47,681 Reputation points
    2020-10-17T15:02:36.177+00:00

    Without seeing an example what's in your "results variable" it's not possible to accurately answer your question. Your goal is also unclear. Are you simply trying to extract every occurrence of that pattern regardless of the IP addresses, or are you trying to extract the IP address from the first occurrence of that pattern and then use the extracted IP address to search the rest of the contents of the "results variable"? Or does "the first occurrence" mean the pattern must appear on the first object found in the "results variable"?

    Here are two variations:

    $x = "NTP(1.134.56.189:123,unicast)", "HTTP(23.235.124.2:80,xxx)", "SMTP(210.24.222.6:25,yyy)","NTP(62.65.87.100:123,unicast,zzz)","NTP(1.134.56.189:123,unicast)"
    
    # look for pattern regardless of IP address
    "Look for all"
    $x |
        ForEach-Object{
            if ($_ -match "(NTP)\((\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?):"){
                "{0} {1}" -f $matches[1], $matches[2]
            }
        }
    
    # get IP from 1st item, then search for that
    "Look for first"
    $lookforthis = ""
    if ($x[0] -match "(NTP)\((\d\d?\d?\.\d\d?\d?\.\d\d?\d?\.\d\d?\d?):"){
        $lookforthis = [regex]::Escape($matches[2])
        $x |
            ForEach-Object{
                if ($_ -match "(NTP)\(($lookforthis):"){
                    "{0} {1}" -f $matches[1], $matches[2]
                }
            }
    }
    
    0 comments No comments

5 additional answers

Sort by: Most helpful
  1. Rich Matheisen 47,681 Reputation points
    2020-10-16T14:42:23.807+00:00

    Are you just looking to find all the connections from remote clients to your NTP server?

    Get-NetTCPConnection -LocalPort 123
    

    From your description I'm not clear if you're looking at this from the NTP server or from a NTP client perspective.

    If it's from a client perspective, change the "-LocalPort" to "-RemotePort".

    If you want to know the process that's using that connection:

    Get-Process -Id (Get-NetTCPConnection -LocalPort 135).OwningProcess
    
    0 comments No comments

  2. YaroC 316 Reputation points
    2020-10-17T08:57:11.99+00:00

    This is a completely different scenario. My question is more about parsing the combined output my script is gathering by running various executable on remote systems. Was hoping the example I mentioned will help me understand how what I'm trying to do can be achieved.

    0 comments No comments

  3. YaroC 316 Reputation points
    2020-10-17T17:11:10.063+00:00

    Thanks for the examples. The first "look for all" with | select -first 1 does exactly what I need :)
    So (\d\d?\d?.\d\d?\d?.\d\d?\d?.\d\d?\d?) is then a way of filtering for a dotted decimal and as I understand ? indicates that although one digit is required there may be 3 in total. Does this notation )( mean we're looking for 2 matches "{0} {1}" and both need to match? What's "-f" for?

    0 comments No comments

  4. Rich Matheisen 47,681 Reputation points
    2020-10-17T18:26:17.797+00:00

    Yes, "\d\d?\d?.\d\d?\d?.\d\d?\d?.\d\d?\d?" is one way to extract that dotted-decimal string. Another is "\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}", but it makes the regex engine do the counting and it can, if you have very large numbers strings to match, be significantly slower. Also note that the regex doesn't discriminate between good and bad IPv4 addresses. It'll accept a bad address like "123.456.789.0". You'd need a more complex regex to deal with some sort of validation. Here's an example of that: ip.html
    The grouping operators "(" and ")" (in the case the regex I used) tell the regex engine to "memorize" the matching string they surround. PowerShell places the results of the -match operator into an object named $matches and the memorized matches are also available in special variables like $1 and \1 for use within the regex if you're using -replace instead of -match.
    The "-f" is PowerShell's "format" operator. The "{n}" is a placeholder, to be replaced by the corresponding item in the list following the -f.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.