Home > Mobile >  Loop through paragraphs, Filter by Where-Object Condition
Loop through paragraphs, Filter by Where-Object Condition

Time:11-04

I am trying to parse through a .txt dump of firewall rules (100 ). I want to search each rule for a specific parameter (ex. set ips-sensor). If that rule contains the parameter, I want the script to print "value found". If not, I want the script to print "value not found". I have treated each rule as a paragraph and used a delimiter on "next". I cannot get the foreach loop to work. Here is what I have:

$paragraphs = Get-Content C:\firewall_rules.txt -Delimiter "next"
#$line = $paragraphs.Split([string[]]"`r`n", [StringSplitOptions]::None)
$exists = $paragraphs | Where-Object { $_ -like '*set ips-sensor*' }  
$noexists = $paragraphs | Where-Object {$_ -notlike '*set ips-sensor*'}
$result = foreach ($line in $paragraphs) {$line.Split([string[]]"`r`n", [StringSplitOptions]::None)}


foreach ($result in $paragraphs)
{
    if (?)
    {
    Write-Host "value found"
    }

    elseif (?)
    {
    Write-Host "value not found"
    }
}

Here is an example of the exact format:

    edit 168
        set name "Office Stuff"
        set srcintf "Office"
        set dstintf "port11"
        set srcaddr "overthere"
        set internet-service enable
        set action accept
        set schedule "always"
        set logtraffic all
        set fsso disable
        set nat enable
    next
    edit 174
        set name "My Policy"
        set srcintf "Office"
        set dstintf "port1"
        set srcaddr "overthere"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set utm-status enable
        set logtraffic all
        set ips-sensor "default"
   next
    edit 68
        set name "Naughty IPs"
        set srcintf "Office"
        set dstintf "port1"
        set srcaddr "all"
        set dstaddr "faraway"
        set schedule "always"
        set service "ALL"
        set logtraffic all
        set ips-sensor "default"
        set fsso disable

my expected output should be -

value not found 
value found 
value found

Any help is appreciated.

CodePudding user response:

Nice question, I've added comments on the code so you can follow the thought process.

# Define the word we want to match
$find = 'ips-sensor'

# Set Paragraph counter
$z = 1

# $file will be an array with 3 elements / paragraphs given the example we got
foreach($paragraph in $file)
{
    # Set the line counter (this will be reset on each paragraph)
    $i = 0

    # Set a result hashtable and assume we will not find the word we're looking for
    $out = [ordered]@{
        Paragraph = $z
        Status = 'Not Found'
        LineNumber = ''
        Line = ''
    }

    # Split this paragraph on new lines and filter only those elements that are 
    # not empty strings and loop through it
    foreach($line in $paragraph -split '\r?\n' -ne '')
    {
        # Increment the line counter
        $i  

        # Self explanatory
        if($line -match $find)
        {
            $out.Status = 'Found'
            $out.LineNumber = $i
            $out.Line = $line.Trim()

            # Break the inner loop, if we are here we don't need to keep looping
            # over this array
            break
        }
    }
    
    # Cast a pscustomobject which can be easily manipulated and exported
    [pscustomobject]$out

    # Increment Paragraph counter
    $z  
}

Result

Paragraph Status    LineNumber Line                    
--------- ------    ---------- ----                    
        1 Not Found                                    
        2 Found     12         set ips-sensor "default"
        3 Found     10         set ips-sensor "default"

If you wanted to find multiple words on your dump file, the code would require a few modifications:

$find = 'ips-sensor', 'naughty' -join '|'
$z = 1

foreach($paragraph in $file)
{
    $i = 0
    $out = [ordered]@{
        Paragraph = $z
        Status = 'Not Found'
        LineNumber = ''
        Line = ''
    }

    foreach($line in $paragraph -split '\r?\n' -ne '')
    {
        $i  

        if($line -match $find)
        {
            $out.Status = 'Found'
            $out.LineNumber = $i
            $out.Line = $line.Trim()

            [pscustomobject]$out
        }
    }

    if($out.Status -eq 'Not Found')
    {
        [pscustomobject]$out
    }

    $z  
}

Result

Paragraph Status    LineNumber Line                    
--------- ------    ---------- ----                    
        1 Not Found                                    
        2 Found     12         set ips-sensor "default"
        3 Found     2          set name "Naughty IPs"  
        3 Found     10         set ips-sensor "default"

CodePudding user response:

Since you've already broken the text up into chunks, they can be passed to a foreach-object and you just simply need to test if the desired string is found.

Get-Content C:\firewall_rules.txt -Delimiter 'next' | ForEach-Object {
    if($_ -Match 'set ips-sensor'){
        "Value found"
    }
    else{
        "Value not found"
    }
}

This produces your desired output.

Value not found
Value found
Value found
  • Related