PowerShell foreach how to skip last element - arrays

I have the follow array with the elements
$list = "A","B","C","1","2","3"
using foreach I can view all items in the array.
foreach ( $item in $list ) { $item }
I would like to print all elements in the array but the last one. As I need to add ; at the end.
How can I go about doing this?

Is this what you're looking for?
$List = "A","B","C","1","2","3";
($List[0..($List.Length-2)] -join '') + ';';
Result
ABC12;

This can also be done in as one-liner:
-join $List -replace [Regex]'.$',';'
First -join sticks all the elements in the array together. Then -replace & regex replace the last element with ;.
Regex ('.$')
. = Matches any character except line breaks.
$ = Matches the end of the string.

Related

PowerShell array, loop first row

I have a problem with array as following with only one line:
$list = #()
$list = (("ResourceGroup","Vm1"))
$list | ForEach-Object -Parallel {
write-output $_[0] $_[1]
}
If I loop that array with one line, PowerShell prints the first 2 letter of each word. If I put 2 or more row like following:
$list = #()
$list = (("ResourceGroup","Vm1"),`
("ResourceGroup","Vm2")
)
PowerShell print correctly the values inside.
There is a way to print correctly the value of an array with only one line?
("ResourceGroup","Vm1") is interpreted as one array with two string elements, where as (("ResourceGroup","Vm1"), ("ResourceGroup","Vm2")) is interpreted as one array with 2 array elements, can be also called a jagged array. If you want to ensure that the first example is treated the same as the second example, you can use the comma operator ,:
$list = , ("ResourceGroup","Vm1")
$list | ForEach-Object -Parallel {
Write-Output $_[0] $_[1]
}
To put it in perspective:
$list = ("ResourceGroup","Vm1")
$list[0].GetType() # => String
$list = , ("ResourceGroup","Vm1")
$list[0].GetType() # => Object[]
Write-Output with the -NoEnumerate switch combined with the Array subexpression operator #( ) can be another, more verbose, alternative:
$list = #(Write-Output "ResourceGroup", "Vm1" -NoEnumerate)
$list | ForEach-Object -Parallel {
Write-Output $_[0] $_[1]
}

Powershell sort-object with number

I have an array of strings make like this "name: number" and I need to order it by number every time that I add another row to the array but the sorting doesn't work.
The idea is that every time that the function is called I create a new row and I add it to the text.
Then, for each row in the text I add in front of the row the number and a '#'.
Now the array is like this:
15#foo:15
2#bar:2
4#foobar:4
Now I'd like to order it by number and then remove the part that I added to sort.
Function Add($name, $number) {
$newRow = "$($name):$number`r`n"
$Script:text = $Script:text + $newRow
ForEach($row in $text.Split("`r`n")) {
if ($row.length -ne 0) {
$rows = $rows + $row.Split(":")[1] + "#" + $row + "`r`n"
}
}
$rows | Sort-Object
ForEach($row in $rows.Split("`r`n")) {
$newText = $newText + $row.Split("#")[1] + "`r`n"
}
$textBox.Text = $newText
}
It all works except the sorting.
Does anyone knows how to fix it?
You can sort your input directly, by passing a script block ({ ... }) to Sort-Object that extracts the number from each input string ($_) and sorts based on it:
PS> 'foo:15', 'bar:2', 'foobar:4' | Sort-Object { [int] ($_ -split ':')[-1] }
bar:2
foobar:4
foo:15
In your case, since the lines are part of a single, multi-line string you need to split the string into individual lines first, then sort them, then rejoin the sorted lines:
(
#'
foo:15
bar:2
foobar:4
'# -split '\r?\n' | Sort-Object { [int] ($_ -split ':')[-1] }
) -join [Environment]::NewLine
The output looks the same as above, but in this case it isn't an array of sorted lines, but a single multi-line string containing the sorted lines.
Note: Sort-Object outputs a new array, it doesn't sort in place. Therefore, to save the sorted array back to the same variable, you must use something like:
$rows = $rows | Sort-Object ...

Powershell to split a string into an array by start and end characters

Given values to extract from a string, where each value is surrounded by a starting character and ending character, what would be the most effective way to achieve this?
eg, to get an array containing values: a b c
$mystring = "=a; =b; =c;"
$CharArray = $mystring.Split("=").Split(";")
There are numerous combinations of -replace, -split, .Split(), and .Replace() that could be used for this task. Here are some examples:
# Since each element is separated by a space, you can replace extraneous characters first
# -split operator alone splits by a space character
# This can have issues if your values contain spaces too
($mystring -replace '=|;').Split(' ')
-split ($mystring -replace '=|;')
# Since splitting creates white space at times, `Trim()` handles that.
# Because you expect an array after splitting, -ne '' will only return non-empty elements
$mystring.Split("=").Split(";").Trim() -ne ''
# Creates a array of of System.Char elements. Take note of the type here as it may not be what you want.
($mystring -replace ' ?=|;').ToCharArray()
# Uses Split(String[], StringSplitOptions) method
($myString -replace ' ?=').Split(';',[StringSplitOptions]::RemoveEmptyEntries)
David, what you have looks good yet here is another way to do it. The -replace method handles the space (" ") and equal sign (=).
$mystring = "=a; =b; =c;"
$CharArray = $mystring -split ";" -replace " |=",""

Perl Array of regular expressions -- matching elements of an array

I am trying to match and remove elements from an array called #array. The elements to be removed must match the patterns stored inside an array called #del_pattern
my #del_pattern = ('input', 'output', 'wire', 'reg', '\b;\b', '\b,\b');
my #array = (['input', 'port_a', ','],
['output', '[31:0]', 'port_b,', 'port_c', ',']);
To remove the patterns contained in #del_pattern from #array, I loop through all the elements in #del_pattern and exclude them using grep.
## delete the patterns found in #del_pattern array
foreach $item (#del_pattern) {
foreach $i (#array) {
#$i = grep(!/$item/, #$i);
}
}
However, I have been unable to remove ',' from #array. If I use ',' instead of '\b,\b' in #del_pattern, element port_b, gets removed from the #array as well, which is not an intended outcome. I am only interested in removing elements that contain only ','.
You are using the wrong regular expression. I updated the code and tried it and its working fine. PFB the update code:
my #del_pattern = ('input', 'output', 'wire', 'reg', '\b;\b', '^,$');
my #array = (['input', 'port_a', ','],
['output', '[31:0]', 'port_b,', 'port_c', ',']);
## delete the patterns found in #del_pattern array
foreach my $item (#del_pattern) {
foreach my $i (#array) {
#$i = grep(!/$item/, #$i);
}
}
The only change made is in the Regex '\b,\b' to '^,$'. I don't have much info on \b but the regex I am suggesting is doing what you intend.
You want
^,\z
An explanation of what \b doesn't match at all follows.
\b
defines the boundary of a "word". It is equivalent to
(?<=\w)(?!\w) | (?<!\w)(?=\w)
so
\b,\b
is equivalent to
(?: (?<=\w)(?!\w) | (?<!\w)(?=\w) ) , (?: (?<=\w)(?!\w) | (?<!\w)(?=\w) )
Since comma is a non-word character, that simplifies to
(?<=\w),(?=\w)
So
'a,b' =~ /\b,\b/ # Match
',' =~ /\b,\b/ # No match
This works, but not very nice from the code.
This code snippet also removes the ','
my $elm = [];
sub extract {
my $elm = shift;
foreach my $del (#del_pattern) {
$elm =~ s/$del//g;
if ( $elm ) {
return $elm;
}
}
}
foreach my $item (#array) {
foreach my $i (#$item) {
my $extract = extract($i);
if ($extract) {
push(#$elm, $extract);
}
}
}
print Dumper($elm);
Why your #array has array? Why not one big array?

Powershell: Format Multidimensional Array for Output

I am exploring options for presenting multidimensional array in some specified format. Desired output is a single line string with elements within each dimension separated by specified character. For example:
$foo = #(#("A","B","C"),#("1","2","3"))
$bar = #()
foreach ($i in $foo)
{
$bar += $i -Join ", "
}
$bar -join "; "
Produces desired output. When number of dimensions in the array grows, or is variable within the nested elements, this approach becomes cumbersome.
I am wondering if exists some Powershell magic to assist with this task. Ideally, something like:
$foo[([] -join ", ")] -join "; "
And perhaps a solution that will scale well for more complex array configurations.
Thoughts?
this way?
$foo = #(#("A","B","C"),#("1","2","3"))
($foo | % { $_ -join ',' }) -join '; '

Resources