Concatenate Arrays as String with PowerShell - powershell

i have two array ($a , $b) which holds the following strings:
$a
MSSQL11.SQLINST15
MSSQL12.SQLINST16
MSSQL12.SQLINST17
$b
2874
2884
2885
That i'm trying to concatenate to a new array ($c), as a strings with a comma sign in the middle:
$c
MSSQL11.SQLINST15,2874
MSSQL12.SQLINST16,2884
MSSQL12.SQLINST17,2885
Problem is, that using my current ps code:
$c = #($a + ',' + $b)
[string]::Concat($c)
$c
I'm getting a very strange output:
MSSQL11.SQLINST15
MSSQL12.SQLINST16
MSSQL12.SQLINST17
,
2887
2884
2885

At the end, i've use a powershell hashtable.

I like this way of doing it. Create a zip function to combine your two arrays into a single array of tuples.
Then it's just a matter of piping piece-wise over that tuple list our zip function gives us. Super convenient and reusable.
function Zip($a, $b) {
while ($a) {
$x, $a = $a
$y, $b = $b
[tuple]::Create($x, $y)
}
}
$c = zip $a $b |% {$_.item1 + [string]$_.item2}
Note you can choose where ya wanna to your [string] conversion (in the following, the last line of zip).
function Zip($a, $b) {
while ($a) {
$x, $a = $a
$y, $b = $b
[tuple]::Create([string]$x, $y)
}
}
$c = zip $a $b |% {$_.item1 + $_.item2}
Extra info: Looks like you're accidentally just combining the two arrays using a ",". But $a and $b are arrays, so what you actually want to do is combine the first element of $a with the first element of $b (aka $a[0] + [string]$b[0], and so on for each element. Why the [0]? Remember we almost always start counting at 0 in programming. So the second item of an array is actually [1].
Edit: Here is an example using a foreach loop.
```
foreach($item in $a) {
$i = $a.IndexOf($item)
$a[$i] + [string]$b[$i]
}
```
If for some reason $a has 10 things in it, and $b only has 2 things, it's gonna give you funny behavior. So be careful there. Please let me know if I can better clarify anything. Don't forget to experiment.

Related

The statements inside the label executes even if the condition fails.Can anyone explain what I'm doing here wrong?

my $a =10;
my $b =200;
my $c,$d;
goto UP if ($a > 20);
$d = $c + $b;
print "$d\n";
UP:
$c = $b -$a;
print "$c\n";
The above statements inside the label executes even if the condition fails.
It seems like you are mixing up how the labels and goto work. In fact, goto should never be used for flow control. It's really confusing.
This is how your code runs at the moment:
As you can see, the last two statements (those are after your UP label) are always executed. Perl will check the condition, and if it is true, skip ahead. If the condition is false, it runs the two statements following immediately, and then runs the label and the rest.
Labels don't make subroutines in Perl. They just give a line a name. The line of code is still executed normally.
If you want to do one or the other instead, you need an if-else construct. That's done like this in Perl.
my $a = 10;
my $b = 200;
my ( $c, $d );
if ($a > 20) {
$c = $b -$a;
print "$c\n";
} else {
$d = $c + $b;
print "$d\n";
}
Since you seem to insist on goto, you can make that work, but you need to tell it to stop execution.
my $a =10;
my $b =200;
my $c,$d;
goto UP if ($a > 20);
$d = $c + $b;
print "$d\n";
exit; # <------------- this stops execution and ends the program
UP:
$c = $b -$a;
print "$c\n";
Of course your code won't do much, because both $c and $d are undef.
You should really turn on use strict and use warnings, and fix the problems both of these pragmata will show you.
Also note that $a and $b are reserved variables to be used inside sort.
The code you posted is equivalent to the following:[1]
A: my $a = 10;
B: my $b = 200;
C: my ($c, $d);
D: goto G if $a > 20;
E: $d = $a + $b;
F: print "$d\n";
G: $c = $b - $a;
H: print "$c\n";
As this better demonstrates, code execution doesn't stop once a label is encountered.
To emulate an if-then-else structure, you'd use
my $a = 10;
my $b = 200;
$a > 20 and goto ELSE;
my $d = $a + $b;
print "$d\n";
goto END;
ELSE:
my $c = $b - $a;
print "$c\n";
END:
You probably know this, but the following is a lot clearer and provides better scoping:
my $a = 10;
my $b = 200;
if ($a <= 20) {
my $d = $a + $b;
print "$d\n";
} else {
my $c = $b - $a;
print "$c\n";
}
After a couple of off-topic fixes

powershell double for loop

Need advice on loop
$Variable contains 11111 22222
foreach ($variable in $value) {
for ([byte]$c = [char]'b'; $c -le [char]'c'; $c++) {
$variable."([char]$c)" } }
I am looking output as 11111b and then 22222c but currently, I am getting 11111b , 11111c and then 22222b and then 22222c.
Kindly advice
I am assuming you mean that $value, not $variable, contains 11111 and 22222, specifically in an array.
Since you want $c to maintain its value between iterations of the foreach loop you need to initialize $c outside of the foreach loop. Therefore, you really don't need (or, rather, should not use) two loops at all.
$value = 11111, 22222;
[Byte] $c = [Char] 'b';
foreach ($variable in $value)
{
"$variable$([Char] $c++)"
}
This gives the output you are seeking:
11111b
22222c

what is the usage of \& and $expr->()

sub reduce(&#) {
my $expr = \&{shift #ARG};
my $result = shift #ARG;
while (scalar #ARG > 0) {
our $a = $result;
our $b = shift #ARG;
$result = $expr->();
}
return $result;
}
I cannot really understand some grammar in this code. Anyone can explain to me? like \& and $result = $expr->()
\&name returns a reference to the subroutine named name.
$code_ref->() calls the subroutine referenced by $code_ref.
$ perl -e'
sub f { CORE::say "Hi" }
my $code_ref = \&f;
$code_ref->();
'
Hi
In your case, shift #ARG returns a subroutine reference. \&{ $code_ref } simply returns the code ref. As such,
my $expr = \&{shift #ARG};
could have been written as
my $expr = shift #ARG;
Note that reduce's prototype allows it to be called as
reduce { ... } ...
but what is actually executed is
reduce( sub { ... }, ... )
Note that this version of reduce is buggy. You should use the one provided by List::Util.
local $a and local $b should have been used to avoid clobbering the values its caller might have in $a and $b.
This version of reduce expects its callback to have been compiled in the same package as reduce itself. Otherwise, the callback sub won't be able to simply use $a and $b.
Declaring the variables using our is actually completely useless in this version case since $a and $b are exempt from use strict; checks, and the undeclared use of $a and $b would access the very same package variables.
Having a look some List::Util::reduce() examples will probably help.
Let's take the first one:
$foo = reduce { $a > $b ? $a : $b } 1..10;
So reduce takes a BLOCK followed by a LIST, which the function signature declares: sub reduce(&#) {. The block in our case is the statement $a > $b ? $a : $b, while the list is 1..10. From the docs:
Reduces #list by calling "BLOCK" in a scalar context multiple times,
setting $a and $b each time. The first call will be with $a and $b set to
the first two elements of the list, subsequent calls will be done by
setting $a to the result of the previous call and $b to the next element
in the list.
Returns the result of the last call to the "BLOCK". If #list is empty then
"undef" is returned. If #list only contains one element then that element
is returned and "BLOCK" is not executed.
And now to an annotated version of the code:
$foo = reduce { $a > $b ? $a : $b } 1..10; # $foo will be set to 10
sub reduce(&#) {
# reduce() takes a BLOCK followed by a LIST
my $expr = \&{shift #ARG};
# $expr is now a subroutine reference, i.e.
# $expr = sub { $a > $b ? $a : $b };
# Start by setting $result to the first item in the list, 1
my $result = shift #ARG;
# While there are more items in the list...
while (scalar #ARG > 0) {
# Set $a to the current result
our $a = $result;
# Set $b to the next item in the list
our $b = shift #ARG;
# Set $result to the result of $a > $b ? $a : $b
$result = $expr->();
}
# List has now been reduced by the operation $a > $b ? $a : $b
return $result;
}

Is powershell assigning lazy?

I have the following code
$a = ls
....
$a | ? { ... }
Will $a be assigned when the first line is executed? Or it will not execute until it hits $a | ? { ... }?
Why the following code not return true?
$b = #(1,2);
$c = $b;
$b -eq $c
First question:
$a is assigned when the first line is executed
try:
$a = ls
$a.gettype(); # now $a is an array of [fileinfo] and/or [directoryinfo]
Second question:
read here
and note:
$b.Equals($c)
return true

Powershell - search for string, remove excess whitespace, print second field

I'm having a problem parsing some string data in powershell and need a little help. Basically I have an application command that doesn't output objects, rather string data.
a = is the item I'm searching for
b = is the actual ouput from the command
c = replaces all the excess whitespace with a single space
d = is supposed to take $c "hostOSVersion 8.0.2 7-Mode" and just print "8.0.2 7-Mode"
However, $d is not working it just prints the same value as $c. I'm a UNIX guy and this would be easy in one awk statement. If you know how to do this in one command that would be nice, or just tell me what's wrong with my $d syntax below.
$a = "hostOSVersion"
$b = "hostOSVersion 8.0.2 7-Mode"
$c = ($a -replace "\s+", " ").Split(" ")
$d = ($y -replace "$a ", "")
Well you might have to futz around with the exact pattern, but one way is with a regex:
$b = "hostOSVersion 8.0.2 7-Mode"
$b -match '(\d.*)'
$c = $matches[1]
If you really wanted to oneline it with -replace:
$($($b -replace $a, '') -replace '\s{2}', '').trim()
Your line
$c = ($a -replace "\s+", " ").Split(" ")
should reference the $b variable instead of $a
$c = ($b -replace "\s+", " ").Split(" ")
Then, you will notice the output of $d becomes
hostOSVersion
8.0.2
7-Mode
and a statement like $d[1..2] -join ' ' would produce 8.0.2 7-Mode