JKelley
JKelley

Reputation: 69

Why Isn't This Counting Correctly | PowerShell

Right now, I have a CSV file which contains 3,800+ records. This file contains a list of server names, followed by an abbreviation stating if the server is a Windows server, Linux server, etc. The file also contains comments or documentation, where each line starts with "#", stating it is a comment. What I have so far is as follows.

$file = Get-Content .\allsystems.csv
$arraysplit = @()
$arrayfinal = @()
[int]$windows = 0

foreach ($thing in $file){
    if ($thing.StartsWith("#")) {
        continue
        }
    else {
        $arraysplit = $thing.Split(":")
        $arrayfinal = @($arraysplit[0], $arraysplit[1])
    }
}

foreach ($item in $arrayfinal){
    if ($item[1] -contains 'NT'){
        $windows++
    }
    else {
        continue
    }
}
$windows

The goal of this script is to count the total number of Windows servers. My issue is that the first "foreach" block works fine, but the second one results in "$Windows" being 0. I'm honestly not sure why this isn't working. Two example lines of data are as follows:

example:LNX

example2:NT

Upvotes: 1

Views: 125

Answers (4)

Maximilian Burszley
Maximilian Burszley

Reputation: 19694

The goal of this script is to count the total number of Windows servers.

I'd suggest the easy way: using cmdlets built for this.

$csv = Get-Content -Path .\file.csv |
    Where-Object { -not $_.StartsWith('#') } |
    ConvertFrom-Csv

@($csv.servertype).Where({ $_.Equals('NT') }).Count

# Compatibility mode:
# ($csv.servertype | Where-Object { $_.Equals('NT') }).Count

Replace servertype and 'NT' with whatever that header/value is called.

Upvotes: 0

curtmcgirt
curtmcgirt

Reputation: 61

if the goal is to count the windows servers, why do you need the array?

can't you just say something like

foreach ($thing in $file)
{
    if ($thing -notmatch "^#" -and $thing -match "NT") { $windows++ }
}

Upvotes: 1

Ketanbhut
Ketanbhut

Reputation: 506

I'd avoid making another ForEach loop for bumping count occurrences. Your $arrayfinal also rewrites everytime, so I used ArrayList.

$file = Get-Content "E:\Code\PS\myPS\2018\Jun\12\allSystems.csv"
$arrayFinal = New-Object System.Collections.ArrayList($null)

foreach ($thing in $file){
    if ($thing.StartsWith("#")) {
        continue
        }
    else {
        $arraysplit = $thing -split ":"
        if($arraysplit[1] -match "NT" -or $arraysplit[1] -match "Windows")
        {
            $arrayfinal.Add($arraysplit[1]) | Out-Null
        }
    }
}

Write-Host "Entries with 'NT' or 'Windows' $($arrayFinal.Count)"

I'm not sure if you want to keep 'Example', 'example2'... so I have skipped adding them to arrayfinal, assuming the goal is to count "NT" or "Windows" occurrances

Upvotes: 0

Jacob Colvin
Jacob Colvin

Reputation: 2835

$arrayfinal = @($arraysplit[0], $arraysplit[1])

This replaces the array for every run.

Changing it to += gave another issue. It simply appended each individual element. I used this post's info to fix it, sort of forcing a 2d array: How to create array of arrays in powershell?.

$file = Get-Content .\allsystems.csv
$arraysplit = @()
$arrayfinal = @()
[int]$windows = 0

foreach ($thing in $file){
    if ($thing.StartsWith("#")) {
        continue
        }
    else {
        $arraysplit = $thing.Split(":")
        $arrayfinal += ,$arraysplit
    }
}

foreach ($item in $arrayfinal){
    if ($item[1] -contains 'NT'){
        $windows++
    }
    else {
        continue
    }
}
$windows

1

I also changed the file around and added more instances of both NT and other random garbage. Seems it works fine.

Upvotes: 0

Related Questions