Powershell Separating a string into an array and iterating through - arrays

I'm trying to separate a string in the following format,
STANDARDWOFFPACK_FACULTY ; FLOW_FREE
So that each entry in the string is an item within an array I can iterate through to do a function against. Any suggestions on how I would achieve this array would be greatly appreciated.

You can use the split() method:
$myString= 'STANDARDWOFFPACK_FACULTY ; FLOW_FREE'
$myString.split(';')
Which gives:
STANDARDWOFFPACK_FACULTY
FLOW_FREE
Note that this includes the extra spaces as part of the separate strings. If you want rid of those, do this:
$myString.split(';').Trim()
To get the output in an array, simply capture it in a variable:
$myArray = $myString.split(';').Trim()
You can confirm it is an array with the GetType() method:
$myArray.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array

Related

Check for a random element in an array and return it if true

I've got several arrays of varying length that may contain an element which begins with foo (the name length varying as well), if this element exists I want to return it, e.g. foo-f-o-o.
I know how to check for its existence, I successfully tested in
{
"arr": [
"foo-f-o-o", "bar", "baz", "qux", "quux", "corge", "grault"
]
}
with the command type file.json | jq ".arr|contains([\"foo\"])" and I correctly received true.
However, I'm looking for these steps:
Detect if an element foo* exists
If yes, return that element's name, in the given case: foo-f-o-o
If not, return false
The element foo.* could be at any position of the array, that means something like jq -r ".arr|.[0]" is not an option here.
Is there a way to apply a regex like /^foo.*/ in jq for the matching value?
You don't need regex for this particular case, use startswith:
first(.arr[] | select(startswith("foo"))) // false
If you need all matching elements:
(.arr[] | select(startswith("foo"))) // false

How to retain trailing zeros in string array parameter without using quotes

PowerShell drops the trailing zero of an array element's value when that value contains a dot. Unless I wrap the value in quotes. Unfortunately I need to retain the trailing zero and the script users fail to use quotes reliably.
How can I coerce PowerShell to preserve the trailing zero?
The array element format is Number.Number
The array element may have 1 to n trailing zeros
Single element arrays retain trailing zeros
Multi element arrays drop trailing zeros
Strongly typing the parameter as [string[]] does not resolve the issue.
Example:
function Get-Customer {
Param
(
[string[]]$CustomerId
)
$CustomerId
}
> Get-Customer -CustomerId 654.1,654.10,654.1721,654.1720
654.1 #CORRECT
654.1 #INVALID
654.1721 #CORRECT
654.172 #INVALID
You cannot preserve that 0 if the caller does not put it in quotes. The fact is that those values will be interpreted as numbers because they fit the pattern of number literals.
So if you can't change your caller's behavior then they will be numbers before they ever enter your function. Your [string[]] cast will convert the number to a string, but it's already a number at that point and will follow number -> string rules.
PowerShell is very lenient when it comes to type conversion, or rather, it tries hard to successfully convert types when there is a mismatch, so it will be difficult to throw an error in this case too (you have no access to the original values to know anything is wrong as this happens during parameter binding).
You could do this:
function Get-Customer {
Param
(
[ValidateScript({
$_ -is [string]
})]
[object[]]$CustomerId
)
$CustomerId
}
It would force the values passed in to already be a [string], which kind of sucks for all the other cases where string conversion would have been useful though.
I'm with briantist, to reduce quoting, you could split one string:
function Get-Customer {
Param
(
[ValidateScript({
$_ -is [string]
})]
[object[]]$CustomerId
)
$CustomerId -split ','
}
> Get-Customer -CustomerId '654.1,654.10,654.1721,654.1720',"1.000,2.00"
654.1
654.10
654.1721
654.1720
1.000
2.00
How about this trick. No commas, no quotes, still getting an array and maintaining all your items as is, like this...
function Get-CustomerId
{ $args }
New-Alias -Name cid -Value Get-CustomerId
cid 654.1 654.10 654.1721 654.1720
# Results
654.1
654.10
654.1721
654.1720

Filtering array of strings with other array of strings in Powershell

I need help filtering a big .CSV file for which a certain row must only contain strings from a predetermined set of strings held in a array returned by another Powershell function.
For example, suppose I have the following to filter:
datastore3
datastore1 vl_datastore2 datastore3
datastore1 vl_datastore2 datastore3
datastore1 datastore3
with the following array of strings through which I must discard any bad row:
datastore1 datastore3 (datastore1 in index 0, datastore3 in index 1)
In other words, my function should automatically get rid of any row that has the "vl_datastore2" substring in it, therefore only the first and last row would remain.
How can I go about this? For now I am able to split the rows to filter into an array of strings ("datastore1 vl_datastore2 datastore3" would thus be an array with 3 strings in it),but I'm having trouble finding the correct way to use any Powershell operator to filter my list correctly.
Thanks in advance!
Don't know if this helps or not, but:
$TestArray = #(
'datastore3'
'datastore1 vl_datastore2 datastore3',
'datastore1 vl_datastore2 datastore3',
'datastore1 datastore3'
)
$Filters = #(
'datastore1',
'datastore3'
)
[regex]$regex = ‘(?i)(‘ + (($Filters |foreach {[regex]::escape($_)}) –join “|”) + ‘)’
$TestArray | Where {-not ($_.split() -notmatch $regex)}
datastore3
datastore1 datastore3
That builds an alternating regex from the strings in the $Filter array so that you can essentially match multiple lines to multiple strings in one operation.
The bit that's building the regex is explained here:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/18/speed-up-array-comparisons-in-powershell-with-a-runtime-regex.aspx
I think I'd go another route and use a flag variable and -notcontains. Run the array to test line by line, split each line, check each piece of the split to see if it's contained in the list of approved terms, and if not set a flag so that the line will not be passed down the pipe.
$TestArray = #("datastore3",
"datastore1 vl_datastore2 datastore3",
"datastore1 vl_datastore2 datastore3",
"datastore1 datastore3")
$Filter = #("datastore1","datastore3")
$TestArray|%{
$SetValid = $True
$_ -split " "|?{$Filter -notcontains $_}|%{$SetValid=$false}
if($SetValid){$_}
}
When run that results in:
datastore3
datastore1 datastore3

How do I get the hash name and key in TCL?

I'm trying to figure out how to get the hash name and key in the following situation. Say I have the following hash value:
set CLIENT(CAR) "Koenigsegg"
If I pass $CLIENT(CAR) into a proc, the value that is passed is "Koenigsegg". Is there a way to also capture the fact that the hash and key storing that value is 'CLIENT' and 'CAR', respectively?
For example:
proc foobar {item} {
set the_item $item
}
foobar $CLIENT(CAR)
In this example, the proc only receives the value of $CLIENT(CAR), which is "koenigsegg". The $item is "koenigsegg", but I don't know what kind of item it is. I'd like to get the hash name "CLIENT" and key "CAR" to know that "koenigsegg" it is a "client car".
You can pass the name of the array into a proc, then use upvar to access it:
proc process_array {arrayName} {
upvar 1 $arrayName myArray
puts "Car is $myArray(CAR)"
}
set CLIENT(CAR) "Koenigsegg"
process_array CLIENT ;# Pass the name of the array, note: no dollar sign
Output:
Car is Koenigsegg
I hope this is what you are looking for.
Update
So, you want to pass two things into the proc: the hash name (Tcl refers to it as "array") and the index name (CAR):
proc process_array {arrayName index} {
upvar 1 $arrayName myArray
puts "My array is $arrayName"
puts "List of indices: [array names myArray]"
puts "Car is $myArray($index)"
}
set CLIENT(CAR) "Koenigsegg"
process_array CLIENT CAR;# Pass the name of the array, note: no dollar sign
Output:
My array is CLIENT
List of indices: CAR
Car is Koenigsegg
Update 2
It seems that the original poster (OP) is asking for something like this:
process_array $CLIENT(CAR)
and expect the proc process_array to figure out the name of the array (CLIENT) and the index (CAR). This is not possible in my knowledge. When Tcl interpreter encounters the line above, it evaluates the $CLIENT(CAR) expression and the line becomes:
process_array Koenigsegg
That means within process_array, the proc has no idea about any array. All it knows is someone has passed to it a string "Koenigsegg".
Now, if you pass into the proc the name of the array, then it can figure out the array's name, any any indices the array has. Please see my previous code.

What is correct syntax for arrays in powershell?

Example1:
Note 2: The comma is also used so
separate items in an array {0,-30}
Example2:
To create an array, we create a
variable and assign the array. Arrays
are noted by the “#” symbol. Let’s
take the discussion above and use an
array to connect to multiple remote
computers: $strComputers =
#(“Server1″, “Server2″, “Server3″)
So, which one is correct or what is the difference ?
Example 2 uses the array cast syntax which allows a single element, for example, to be treated as an array:
$myList = #("Hello")
Essentially, it allows anything between the parenthesis to be treated as an array including the output from other commands:
$myArray = #(Get-Process Excel)
Alternatively you can just create an array by specifying a comma separated list:
$myArray = "hello", "world", "again"
(The curly brackets are not needed)
You can also attain a single element array by prepending the , operator to a single value:
[PS] C:\>$a = ,"Hello World"
[PS] C:\>$a.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
[PS] C:\>$a.count
1

Resources