Considering duplicate sections, how to find sections that match certain criteria using Powershell
I need to parse a text file and extract data from it ... based on other data in the same file ..
I need to find the lines that say not ok and then find the nodes they are in. I know how to pull data in ... and find Not Ok and Nodes. I also have an idea that I'm sure it's too hard to find what I'm looking for. I can split the Node strings into an array so that
$test = (select-string -path C:\error.txt -Pattern "Node:").linenumber
then find the line number not oks and backup lol, but that seems like the hardest way to do it. I'm familiar with PS, but not an expert.
$test2 = (select-string -path C:\error.txt -Pattern "Not ok").linenumber
to describe what I need.
parse the file for Node .. find the lines below that do not fit .. and if so set Node to a variable ... if not ok not found, go to next Node.
Thanks for any help
Sample txt file below
Node: Server
*********************
Line 1 ok
line 2 ok
line 3 ok
Line 4 Not ok
line 5 ok
line 6 ok
*********************
Node: Server2
*********************
Line 1 ok
line 2 ok
line 3 Not ok
Line 4 ok
line 5 ok
line 6 ok
*********************
source to share
$errorNodes = @() Get-Content C:\temp\test.txt | ForEach-Object { if ($_ -imatch 'Node: (.+)$') { $node = $Matches[1] } if ($_ -imatch 'not ok') { $errorNodes += $node } } $errorNodes
Description
-
Get-Content
reads the file line by line. - For each line, first check if it is a node; if so, set the variable to the
$node
current node name. - Then check if the string matches the text "not ok". If so, add the node name to the list of error nodes (array variable
$errorNodes
.
So, in the end it $errorNodes
will contain nodes with problems.
source to share
If your list is long this should be a faster way to parse (also less code :)):
$nodes = [Regex]::Split((Get-Content info.txt), 'Node:')
# '?' is an alias for Where-Object
$bad = $nodes | ? { $_.ToLower().Contains('not ok') }
$bad
now also contains all the text under the node containing "not normal" (there are several lines in the even that do not fit).
source to share
This answer is most likely more complex than it should be, but it returns useful objects that, depending on what else needs to be done in his code, might be useful for further processing. In this example, I used the OP's file structure and added some additional nodes to make the output a little more verbose.
$file = Get-Content "c:\temp\test.txt" -Raw
$file -split '\s+(?=Node: \w+)' |
%{ $stringData = (($_ -replace ": "," = ") -replace 'line\W+(\d+)\W+','Line$1 = ') -replace '\*+'
New-Object PSObject -Property $(ConvertFrom-StringData $Stringdata)
} | select node,line* | Format-Table
Using PowerShell 3.0: The code will read the file as a whole string (without creating a string array) using a parameter -Raw
. $file
is a string, split into "Node:" text, which breaks up the nodes as separate objects.
To create a custom object, we need to make sure that all Node elements contain name = value pairs. For this I have nested several operations -replace
.
-
$_ -replace ": "," = "
- change the first line to "Node = server name" -
-replace 'line\W+(\d+)\W+','Line$1 = '
- ConvertLine # ok
toLine# = Ok\Not Ok
Where # is a specific string 1-6 -
-replace '\*+'
- To remove lines containing only asterisks (or something else),
The formed string is used as input for New-Object PSObject -Property $(ConvertFrom-StringData $Stringdata)
After that, we can manipulate the output pipeline like any other object. To ensure that Node appears in the list in the instructions select-object
.
Below is my example:
Node Line4 Line5 Line6 Line1 Line2 Line3
---- ----- ----- ----- ----- ----- -----
Server Not ok ok ok ok ok ok
Server2 ok ok ok ok ok Not ok
Server4 ok ok ok Not ok ok ok
Server3 ok ok ok ok ok ok
source to share