Shrout1
Shrout1

Reputation: 2607

PowerShell split string into two dimensional array

TL:DR

Using PowerShell I want to split a string of text first by the new line character (\n), store it into an array, then split those array entries with a comma into a two-dimensional array. I am having trouble accessing (or possibly creating) any information in the second dimension.

INFO:

I have the following string (stored as $services):

SUPER-PC,Microsoft Office ClickToRun Service,ClickToRunSvc,C:\Program Files\Microsoft Office 15\ClientX64\OfficeClickToRun.exe /service,Auto
SUPER-PC,Adobe Acrobat Update Service,AdobeARMservice,C:\Program Files (x86)\Common Files\Adobe\ARM\1.0\armsvc.exe,Auto

Desired result:

I want to split the string twice:

  1. Split on the new line (first dimension)
  2. Split on the commas within the line (second dimension)

I want the end result of this to be a two dimensional array that I can reference. (Ex: $services[0][0] etc.)

Commands Used:

To accomplish the new line split I have been using the following command:

$services= $services -split "\n"

To access the split string in the new array structure I can do the following:

$services[0]

PowerShell displays only the first line of $services

Next I use:

$services[0] = $services[0] -split ','

Problem:

When I attempt to access the second dimension of the first array using $services[0][0] it displays S which is the first character of the character array ("SUPER-PC" being the start of the string), not the two-dimensional array I want to create.

Where am I going wrong?

Upvotes: 4

Views: 5657

Answers (4)

Esperento57
Esperento57

Reputation: 17462

try this

$Services=("SUPER-PC,Microsoft Office ClickToRun Service,ClickToRunSvc,C:\Program Files\Microsoft Office 15\ClientX64\OfficeClickToRun.exe /service,Auto",
"SUPER-PC,Adobe Acrobat Update Service,AdobeARMservice,C:\Program Files (x86)\Common Files\Adobe\ARM\1.0\armsvc.exe,Auto")

$ConvertedServices = $Services | ConvertFrom-String -Delimiter "," -PropertyNames 'ComputerName','ServiceDescription','ServiceName','CommandLine','StartUp'
$ConvertedServices[0].ComputerName

Upvotes: 2

Shrout1
Shrout1

Reputation: 2607

Ok I hate to self answer, but this was far more simple than I thought... Both other answers are valid, and Mathias pointed me to an obvious oversight.

$string = $string -split "," is not the same as $string = $string.split(",") As Mathias said:

-split returns an object of type string[], meaning that you can't assign anything other than a string to a single item without changing the type of the entire array.

So I ended up utilizing:

$services= $services.split("`r`n")

and then

$services[0]= $services[0].split(",")

I was then able to successfully access the second dimension of the multi-dimensional array using services[0][0]

Also, Bacon Bit's answer is in all likelihood better than my answer; my answer just addresses my question in the simplest possible fashion.

Upvotes: 4

Bacon Bits
Bacon Bits

Reputation: 32145

Is there some reason you're not doing something like this:

$ConvertedServices = $Services | ConvertFrom-Csv -Header 'ComputerName','ServiceDescription','ServiceName','CommandLine','StartUp'

And then:

$ConvertedServices[0].ComputerName

Multidimensional arrays in PowerShell do work, but they're kind of flaky to work with, IMX, especially with strings because strings are often treated as character arrays like you're experiencing here.

Upvotes: 4

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174465

-split returns an object of type string[], meaning that you can't assign anything other than a string to a single item without changing the type of the entire array.

What happens instead, when the parser sees that you're trying to assign a new array to one of the items in the existing $services string array, it automatically converts the new array to a string, concatenated by $OFS. Since $OFS defaults to a space, you essentially turn this string:

SUPER-PC,Microsoft Office ClickToRun Service,ClickToRunSvc,C:\Program Files\Microsoft Office 15\ClientX64\OfficeClickToRun.exe /service,Auto

into this string:

SUPER-PC Microsoft Office ClickToRun Service ClickToRunSvc C:\Program Files\Microsoft Office 15\ClientX64\OfficeClickToRun.exe /service Auto

Instead, create an entirely new array to hold the resulting arrays:

$Services = @'
SUPER-PC,Microsoft Office ClickToRun Service,ClickToRunSvc,C:\Program Files\Microsoft Office 15\ClientX64\OfficeClickToRun.exe /service,Auto
SUPER-PC,Adobe Acrobat Update Service,AdobeARMservice,C:\Program Files (x86)\Common Files\Adobe\ARM\1.0\armsvc.exe,Auto
'@

# I prefer a more OS-agnostic newline pattern
$Services = $Services -split "`r?`n"

# Create a new array, defaults to Object[], so can contain arrays as well
$MultiDimensionalServices = @()

# Iterate over each string in $Services
foreach($ServiceString in $Services){
    # use the unary array operator (,) to avoid flattening the array
    $MultiDimensionalServices += ,@($ServiceString -split ',')
}

Upvotes: 7

Related Questions