Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PowerShell array to store strings

I have a list of files that I am breaking up into parts. That works, but I want to be able to reference each part individually. The issue is with my array not wanting/being able to take in a string. The file naming format is custID_invID_prodID or custID_invID_prodID_Boolvalue.

$files = Get-ChildItem test *.txt
[string]$custId = $files.Count
[string]$invID = $files.Count
[string]$prodID = $files.Count
[int]$Boolvalue = $files.Count
foreach($file in (Get-ChildItem test *.txt)) {
    for($i = 0; $i -le $files.Count; $i++){
        $custId[$i], $invID[$i], $prodID[$i], $Boolvalue[$i] = $file.BaseName -split "_"
        Write-Host $custId, $invID, $prodID, $Boolvalue
    }
}

The error message I am seeing is:

Unable to index into an object of type System.String.

How can I do this?

like image 320
Grady D Avatar asked Feb 19 '14 15:02

Grady D


People also ask

How do I create an array of strings in PowerShell?

To create a string array, we can declare the variable name. Another way is to create using the @(). One more way is by creating the system. collections.

How do I create an ArrayList in PowerShell?

Creating PowerShell ArrayList Collections Collections namespace within . NET. By creating a new object of this type you can then store objects within an ArrayList. Below you can see that you need to explicitly create an ArrayList object using the New-Object cmdlet or by casting a standard array to an ArrayList object.

How do I store multiple values in a variable in PowerShell?

In PowerShell, you can assign values to multiple variables using a single command. The first element of the assignment value is assigned to the first variable, the second element is assigned to the second variable, the third element to the third variable. This is known as multiple assignment.

What does @() mean in PowerShell?

Array subexpression operator @( )Returns the result of one or more statements as an array. The result is always an array of 0 or more objects. PowerShell Copy.


3 Answers

I'd suggest working with objects instead of a lot of string arrays. I have an example below in which I have replaced the file listing, since I don't have the file structure in place, with an ordinary array. Just remove that array declaration and put in your Get-ChildItem call and it should work just fine.

function ConvertTo-MyTypeOfItem
{
    PARAM (
        [ValidatePattern("([^_]+_){3}[^_]+")]
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$StringToParse
    )

    PROCESS {
        $custId, $invId, $prodId, [int]$value = $StringToParse -split "_"
        $myObject = New-Object PSObject -Property @{
            CustomerID = $custId;
            InvoiceID = $invId;
            ProductID = $prodId;
            Value = $value
        }
        Write-Output $myObject
    }
}

# In the test scenario I have replaced getting the list of files
# with an array of names. Just uncomment the first and second lines 
# following this comment and remove the other $baseNames setter, to
# get the $baseNames from the file listing

#$files = Get-ChildItem test *.txt
#$baseNames = $files.BaseName
$baseNames = @(
    "cust1_inv1_prod1_1";
    "cust2_inv2_prod2_2";
    "cust3_inv3_prod3_3";
    "cust4_inv4_prod4_4";
)

$myObjectArray = $baseNames | ConvertTo-MyTypeOfItem 

$myObjectArray

The above function will return objects with the CustomerID, InvoiceID, ProductID and Value properties. In the sample above, the function is called and the returned array value is set to the $myObjectArray/code> variable. When output in the console it will give the following output:

InvoiceID                CustomerID               ProductID                                  Value
---------                ----------               ---------                                  -----
inv1                     cust1                    prod1                                          1
inv2                     cust2                    prod2                                          2
inv3                     cust3                    prod3                                          3
inv4                     cust4                    prod4                                          4
like image 200
Robert Westerlund Avatar answered Sep 30 '22 19:09

Robert Westerlund


Seems to me that you're doing it the hard way. Why 4 arrays for every "field" of a file? It's better to create array of arrays - first index would indicate a file, and second a field in file:

$files = Get-ChildItem test *.txt

$arrFiles = @(,@());
foreach($file in $files ) {
    $arrFile = $file.BaseName -split "_"
    $arrFiles += ,$arrFile;
}
Write-Host "listing all parts from file 1:"
foreach ($part in $arrFiles[1]) {
    Write-Host $part
}
Write-Host "listing part 0 from all files":
for ($i=0; $i -lt $arrFiles.Count ; $i++) {
    Write-Host $arrFiles[$i][0];
}
like image 44
AdamL Avatar answered Sep 30 '22 18:09

AdamL


Because you're trying to index into an object of type System.String! You set all your variables as strings to start with and then try to assign to an index, which I presume would attempt to assign a string to the character position at the index you provide.

This is untested but should be in the right direction.

$custIdArr = @()
$invIDArr = @()
$prodIDArr = @()
$BoolvalueArr = @()
foreach($file in (Get-ChildItem test*.txt)) {
    $split = $file.BaseName -split "_"
    $custId = $split[0];  $custIdArr += $custId
    $invID = $split[1];  $invIDArr += $invId
    $prodID = $split[2];  $prodIDArr += $prodID
    $boolValue = $split[3];  $boolValueArr += $boolValue
    Write-Host $custId, $invID, $prodID, $Boolvalue
}

Create a set of empty arrays, loop through your directory, split the filename for each file, append the results of the split into the relevant array.

I'm assigning to $custId, $invID, $prodID, $Boolvalue for the sake of clarity above, you may choose to directly add to the array from the $split var i.e. $invIDArr += $split[1]

like image 29
arco444 Avatar answered Sep 30 '22 17:09

arco444