Suppose I have an array with random values in it, like for instance
$a=#(0..5)
and I would like to format that array in a string like this :
{0,1,2,3,4}
comma separated values between curly braces. The "catch" is that I don't know in advance the size of the array, and in some cases, when there's only one record the type won't be array but psobject, when it's a unique PSObject I don't need curly braces and commas, I want to leave it as it is.
Thanks!
I would go for this (if statement on the input object type, and use of #beatcracker's method) :
Code :
//insert an array and a custom object in an input array
$input = #(#(0, 1, 2, 3, 4, 5),
[PSCustomObject]#{ title = "My"; first = "Custom"; last = "Object" })
//an empty output array
$output = #()
//foreach item in the input array
foreach($item in $input) {
//if item base type is array
if($item.GetType().BaseType.Name -eq "Array") {
//process and add to output array
$output += "{{{0}}}" -f ($item -join ",")
} else {
//add to output array as-is
$output += $item
}
}
//echo output array
$output
Output :
{0,1,2,3,4,5}
title first last
----- ----- ----
My Custom Object
Info : {0} is a placeholder for the 1st value after -f, ($item -join ",") ; the next one would have been {1} (more info here).
Additional curly brackets are there to escape surrounding curly brackets to make sure they appear in the final string.
Related
I am trying to create a PowerShell script that creates folders (nested and multiple). I managed to get the nested folders to work, and I am pretty new to this, but I cant seem to get the multiple folders to work. I basically want to make a string array with each item being a user inputted string. I tried everything but it just doesn't seem to work, any help would be greatly appreciated, heres my code
echo "Folder Creator for FS2019 by Skaytacium, enter the values for unlimited nested folders! Remember though, 260 characters is the max nesting limit!"
$count = Read-Host -Prompt 'How many folders? Value'
$count = [int16]$count
$sub = Read-Host -Prompt 'Do you wanna nest? 2/1'
$namestring = "./"
$storay
[string]$array = "0", "0", "0"
$arac = 0
$arac = [int16]$arac
if ($sub -eq "2") {
echo "The specified folders will be nested"
while ($count -gt 0) {
$namestring = $namestring + (Read-Host -Prompt 'Name') + "/"
$count--
echo $namestring
if ($count -eq 0) {
md $namestring
}
}
}
elseif ($sub -eq "1") {
echo "The specified folders will be consecutive (in the same dir)"
while ($count -gt 0){
$storay = Read-Host "Name"
$array[1] = #("please help")
echo $array
$arac++
$count--
}
}
Pause
Thanks,
Sid
Replace:
[string] $array = "0", "0", "0" # !! creates *single* string
with:
[string[]] $array = "0", "0", "0" # creates *array* of strings
In your original command, the [string] type constraint to the left of the variable caused the input array (which is implicitly of type [object[]]) to be converted to a single string ([string]) with contents 0 0 0
(PowerShell stringifies arrays by concatenating their elements with separator $OFS, which defaults to a space.)
By contrast, [string[]] results in an array, whose elements are string-typed.
A [...]-enclosed literal in PowerShell refers to a .NET type. It is called a type literal.
If you place such a type literal to the left of variable assignment, you type-constrain that variable, meaning that it can only store values that are instances of that type, and that it automatically tries to convert instances of other types to that type, if possible; see this answer for more information about type constraints.
You can also use a type literal to cast expressions to that type (as your code does in statement $arac = [int16] $arac), which also means converting the operand to that type, as a one-time operation.
In type literal [string[]], the [] after the type name, string, specifies an array of elements of that type; except for the enclosing [...], this notation is the same as the one used by the .NET Type.GetType() method; see this answer for more information.
Note that PowerShell's type conversions are much more flexible than C#'s for instance; they are augmented by built-in conversion rules and attempts to automatically use appropriate constructors and static .Parse() methods.
Note that you don't strictly need the type constraint [string[]], except if you want to make sure that assigning to elements of this array later automatically performs to-string conversion.
# OK, but creates [object[]] array that now happens to contain [string]
# instances, but the type of the elements isn't locked in.
$array = "0", "0", "0"
As for the specific error message you saw:
Because $array was just a single [string] in your code, indexing with, say, [0] indexes in the string's character array.
Technically, this works for getting characters from the array, but you cannot set them:
# GET the 1st character from the string stored in $var
PS> $var = 'foo'; $var[0]
f # 1st character in the string
# !! You CANNOT SET characters that way
PS> $var[0] = 'F'
InvalidOperation: Unable to index into an object of type "System.String".
I have an array of strings in Powershell. For each element I want to concatenate a constant string with the element and update the array at the corresponding index. The file I am importing is a list of non-whitespace string elements separated by line breaks.
The concatenation updating the array elements does not seem to take place.
$Constant = "somestring"
[String[]]$Strings = Get-Content ".\strings.txt"
foreach ($Element in $Strings) {
$Element = "$Element$Constant"
}
$Strings
leads to the following output:
Element
Element
...
Following the hint of arrays being immutable in Powershell I tried creating a new array with the concatenated values. Same result.
What do I miss here?
you concatenate the values to the local variable $Element but this does not change the variable $Strings
here is my approach, saving the new values to $ConcateStrings. by returning the concatenated string and not assigning it to a local variable the variable $ConcateStrings will have all the new values
$Constant = "somestring"
$Strings = Get-Content ".\strings.txt"
$ConcateStrings = foreach ($Element in $Strings) {
"$Element$Constant"
}
$ConcateStrings
Just to show an alternative iterating the indices of the array
$Constant = "somestring"
$Strings = Get-Content ".\strings.txt"
for($i=0;$i -lt $Strings.count;$i++) {
$Strings[$i] += $Constant
}
$Strings
Sample output with '.\strings.txt' containing one,two,three
onesomestring
twosomestring
threesomestring
I am running below script and retrieve information from the template and assign permission. Here I would like to get the User as array input my below script is not processing the user as array.
$userObj = [PSCustomObject]((Get-Content -Raw C:\txt\sample.txt) -replace ':','=' | ConvertFrom-StringData)
[array]$userObj.User
for ($i[0]; $userObj.user; $i++) {
Add-MailboxPermission -Identity $userObj.Identity -User $userObj.User -AccessRights FullAccess -InheritanceType All -confirm:$false
}
Here is my text input which is converted as custom object
$userObj.User is a string with comma-separated names. Casting it to an array just gives you an array with one string with comma-separated names, not an array of the names.
[array]$userObj.User ⇒ [ 'auto,auto1' ]
[array]$userObj.User ⇏ [ 'auto', 'auto1' ]
To get an array of the names from the comma-separated string you need to split it:
$userObj.User -split ','
Also, your for loop is broken. Those loops have the following structure:
for (loop variable initialization; condition; loop variable incrementation)
e.g.
for ($i=0; $i -lt 10; $i++)
But you probably don't need a for loop here anyway. If you want to run a command for each element of the array resulting from your split operation use a ForEach-Object instead:
$userObj.User -split ',' | ForEach-Object {
Add-MailboxPermission -Identity $userObj.Identity -User $_ ...
}
So I have the following ArrayList stored in $var:
ip_prefix region string
0.0.0.0/24 GLOBAL Something
0.0.0.0/24 GLOBAL Something
0.0.0.0/24 GLOBAL Something
0.0.0.0/24 GLOBAL Something
I need to add a row to this however the following code returns an error:
$var.add("127.0.0.1/32", "GLOBAL", "something")
Error:
Cannot find an overload for "Add" and the argument count: "3".
At line:1 char:1
+ $awsips.add("127.0.0.1/32", "GLOBAL", "SOMETHING")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
I'm sure it's something simple I have to adjust, however Google searches had me going around in circles.
$var = New-Object System.Collections.ArrayList
$var.Add(#{"ip_prefix" = "0.0.0.0/24"; "region" = "GLOBAL"; string = "Something"})
$var.Add(#{"ip_prefix" = "127.0.0.1/32"; "region" = "GLOBAL"; string = "SOMETHING"})
$var
$var | %{ Write-Output "$($_.ip_prefix), $($_.region), $($_.string)" }
Or:
$var = #()
$var += #{"ip_prefix" = "0.0.0.0/24"; "region" = "GLOBAL"; string = "Something"}
$var += #{"ip_prefix" = "127.0.0.1/32"; "region" = "GLOBAL"; string = "SOMETHING"}
Should do the job
$obj = New-Object PSObject -Property #{
ip_prefix = "0.0.0.0/24"
region = "GLOBAL"
string = "Something"
}
$var+= $obj
Your output suggests that your array list contains custom objects with properties ip_prefix, region, and string.
You therefore need to add a single object with the desired property values to your array list.
By contrast, you attempted to add 3 indvividual elements to the array list, which is not only conceptually wrong, but also fails syntactically, given that the .Add() method only accepts a single argument (technically, there is a method for adding multiple items, .AddRange()).
In PSv3+, syntax [pscustomobject]#{...} constructs a custom object from a hashtable literal with the definition order of the entries preserved.
$null = $var.Add(
[pscustomobject] #{ ip_prefix="127.0.0.1/32"; region="GLOBAL"; string="something" }
)
Note how $null = ... is used to suppress the .Add() method's output (the index at which the item was inserted).
SQLAndOtherStuffGuy's answer is on the right track, but beware that $var += ... silently replaces the array list stored in $var with a regular PowerShell array ([System.Object[]]).
How can I input multiple values in PowerShell and have those values stored in a variable?
For example:
$value = Read-Host "Enter the value's" #I need 15 values to be entered.
And then recall them e.g:
$value[0] = 1233
$value[1] = 2345
To do this you could declare an array #() and then use a loop and the addition operator to add items to the array (stopping when a blank value is submitted):
$values = #()
Do{
$value = read-host "Enter a value"
if ($value) {$values += $value}
}Until (-not $value)
You can then retrieve values as you described via the index with square brackets []:
$values #returns all values
$values[3] #returns the fourth value (if you entered four or more)
Beware that arrays start from 0, so the first item is [0], second is [1] etc. With PowerShell you can also use negative numbers to work through the array backwards, so [-1] is the last item, [-2] the second to last, etc.
Stores the readin values in an array:
$values = #()
$i = $null
while ($i -ne "q") {
if ($i -ne $null) {
# Attach value to array
$values += $i
}
$i = Read-Host "Enter value (stop with q)"
}
# Print each value in a seperate line
$values | % { Write-Host $_}
# Print type -> to visualize that it is an array
$values.GetType()
# Several values can be retrieved via index operator
$values[0]