I need to count occurrences in file text of a list ip.
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
8.8.8.8
1.1.1.1
1.1.1.1
1.1.1.1
1.1.1.1
I've tried:
Get-Content "C:\listip.txt" | Select-String -Pattern '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' | measure
But I received the total and not the sum of each occurrence. On linux I would have simply used uniq -c
CodePudding user response:
As suggested by Santiago Squarzon, simply pipe into Group-Object
:
Get-Content "c:\listip.txt" |
Select-String -Pattern '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' |
Group-Object -NoElement |
Select-Object Count, @{ n='IP'; e='Name' }
Output:
Count IP
----- --
4 1.1.1.1
9 8.8.8.8
The parameter -NoElement
removes the Group
property that is output by default by Group-Object
, but is not needed for counting only.
I've added Select-Object
to rename the Name
property to IP
, using a calculated property .
If you'd like to correctly sort the unique IPs (i. e. not string sort, but number by number), you might look at this answer.
CodePudding user response:
The alternative to Group-Object
can be using a hash table:
Get-Content C:\listip.txt | & {
begin { $out = @{} }
process { $out[$_.Trim()] = 1 }
end { $out }
}
Output from the anonymous function would be:
Name Value
---- -----
1.1.1.1 4
8.8.8.8 9
If you want to filter or target only the lines that match your pattern, you can add an if
condition and use the Matching Operator -match
:
Get-Content C:\listip.txt | & {
begin { $out = @{} }
process {
# if the line matches this pattern there is for sure no need to `.Trim()`
if($_ -match '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$') {
$out[$_] = 1
}
}
end { $out }
}