You can pass scriptblocks to some cmdlets, in this case Sort-Object and Group-Object. To clarify a bit more:
Load the data
Get-Content foo.txt |
Group by the number (ignoring the suffix, if present):
Group-Object { $_ -replace '\..*$' } |
This will remove non-digits at the end of the string first and use the remainder of the string (hopefully now just containing a floating-point number) as the group name.
Sort by that group name, numerically.
Sort-Object { [int] $_.Name } |
This is done simply by converting the name of the group to a number and sort by that, similar to how we grouped by something derived from the original line.
Then we can get the last two groups, representing all lines with the maximum number and second-to-maximum number and unwrap the groups. The -Last parameter is fairly self-explanatory, the -ExpandProperty selects the values of a property instead of constructing a new object with a filtered property list:
Select-Object -Last 2 -ExpandProperty Group
And there we are. You can try this pipeline in various stages just to get a feeling for what the commands to:
PS Home:\> gc foo.txt
1.0
1.0a
10.0
10.0b
11.0
11.0f
2.0
3.0
4.0
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'}
Count Name Group
----- ---- -----
2 1.0 {1.0, 1.0a}
2 10.0 {10.0, 10.0b}
2 11.0 {11.0, 11.0f}
1 2.0 {2.0}
1 3.0 {3.0}
1 4.0 {4.0}
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'} | sort {[int]$_.Name}
Count Name Group
----- ---- -----
2 1.0 {1.0, 1.0a}
1 2.0 {2.0}
1 3.0 {3.0}
1 4.0 {4.0}
2 10.0 {10.0, 10.0b}
2 11.0 {11.0, 11.0f}
PS Home:\> gc foo.txt | group {$_ -replace '\..*$'} | sort {[int]$_.Name} | select -l 2 -exp group
10.0
10.0b
11.0
11.0f
If you need the items within the groups (and this in the final result for the last two groups) sorted by suffix, you can stick another Sort-Object directly after the Get-Content.