Powershell For Loop In Reverse - powershell

I have the following code:
$testString = "abcdef"
for ($ia=$testString.length-1; $ia -gt 0; $ia - 2) {
$testString[$ia]
}
I need output "fedcba"
But keep getting "fffffffffff..."
How can I reverse the testString output by each character in this for loop format?

Another way with a reverse range in the array index. It should really start at length-1, but it's easier this way and it works. I wish I could do [-1..0] ([-1..-100]?).
$teststring = 'abcdef'
$teststring[$teststring.length..0]
f
e
d
c
b
a
-join $teststring[$teststring.length..0]
fedcba
-join $teststring[-1..-$teststring.length]
fedcba

Why are you using $ia - 2 ?
You need to change that to $ia-- so it decrements one at a time.
Also change $ia -gt 0 to $ia -ge 0 so it reaches the last index.

You almost got it.
$testString = "abcdef"
for ($ia=$testString.length-1; $ia -ge 0; $ia--) {
$testString[$ia]
}
You can use $ia-- to decrement down and you should get your result. Also, you should use -ge for greater than or equal to 0 as you want to capture index 0 of the array.
Also, vice versa, you can do the following:
$testString = "abcdef"
for ($ia=$testString.length; $ia -gt -1; $ia--) {
$testString[$ia]
}
Both works, but I prefer the second one as it's easier to read.

Just to make you aware that there is also a static dotnet Reverse method from the [Array] class:
$CharArray = $teststring.ToCharArray()
[Array]::Reverse($CharArray)
$CharArray
f
e
d
c
b
a
Related GitHub purpose: #16644 Add -Reverse parameter to Sort-Object

Related

Loop through multiple array in powershell

I have 2 arrays here one contains the servername and other contains the IP.
I need to loop through them and create a key value pair like below for each server
server1:ip1
server2:ip2
I have written below code, but the problem is if i debug the code using F11, it is working fine, but i don't it gives some error which is different every time.
so feeling like it is not that reliable piece to continue.
$NewDNSEntryName = $DNSEntryName.Split(",")
$DNSIPs = $DNSIP.Split(",")
if($DNSEntryName -match "," -or $DNSIP -match ",")
{
0..($NewDNSEntryName.Count - 1) | ForEach-Object {
$fullName=""
$fullName += #("$($NewDNSEntryName[$_]):$($DNSIPs[$_])")
This is the line where i am facing trouble
0..($NewDNSEntryName.Count - 1) | ForEach-Object
Please let me know why this code is behaving like this else any alternate idea is appreciated
Assuming each item in each list corresponds with each other exactly, you can use a for loop and loop through the array indexes.
$NewDNSEntryName = $DNSEntryName.Split(",")
$DNSIPs = $DNSIP.Split(",")
for ($i = 0; $i -lt $DNSIPs.count; $i++) {
"{0}:{1}" -f $NewDNSEntryName[$i],$DNSIPs[$i]
}
For the code above to work, $DNSEntryName and $DNSIP must be single strings with commas between names and IPs. If $DNSEntryName and $DNSIP are already lists or arrays, something else will need to be done.
In your attempt, technically, your logic should work given everything written above is true. However, $fullName is emptied at every single iteration, which may produce undesirable results.

Determine if an integer is greater than or equal to a list of integers in powershell

I have two lists of numbers and I want to compare list A to list B in such a way that I go through list A line by line and determine if that number is less than the number in B and then move to the next like of B and repeat.
If the number in A is found to be less than B I would like to return the number in A along with the "match" from B.
I've been trying nested loops and haven't gotten off the ground with this.
Any suggestions for me to try would be very helpful.
Thanks!
This is my "code" if you want to call it that.
$chrIVsite = #("322592","425559","427431")
$SNPCsite = #("28860","43205","279260","481810")
foreach ($read in $chrIVsite)
{
foreach ($site in $SNPCsite) {
if ($_.read -le $_.SNPCsite)
{"$_.read"+"`t"+"$_.SNPCsite"
}
} }
export-csv 'testing.txt' -delimiter "`t" -notype
My expected outcome would be:
425559 481810
427431 481810
Thanks to #AnthonyStringer I just had some simple issues.
This code:
$chrIVsite = #("322592","425559","427431")
$SNPCsite = #("28860","43205","279260","481810","481812","481814")
foreach ($read in $chrIVsite)
{
foreach ($site in $SNPCsite) {
if ([int]$read -le [int]$site)
{"$read"+"`t"+"$site"
}
} }
My out put looks like this:
322592 481810
322592 481812
322592 481814
425559 481810
425559 481812
425559 481814
427431 481810
427431 481812
427431 481814

How can I set a variable in a conditional statement?

I have a script that checks the health of a pc by parsing through log files looking for indicators of compromise. If the script finds a certain event id it returns a normalized message. The end goal is to do math on these returns- this will generate a health score for that PC.
What I need to know is how set a variable (say X with a value of 1) if the event id is found, and set the same variable (say X with a value of 2) if the event id is not found. If I just set both variables in the script -in their respective if/else blocks, won't the last variable always overwrite the first regardless of the condition?
Unfortunately PowerShell doesn't have a conditional assignment statement like Perl ($var = (<condition>) ? 1 : 2;), but you can assign the output of an if statement to a variable:
$var = if (<condition>) { 1 } else { 2 }
Of course you could also do the "classic" approach and assign the variable directly in the respective branches:
if (<condition>) {
$var = 1
} else {
$var = 2
}
The second assignment doesn't supersede the first one, because only one of them is actually executed, depending on the result of the condition.
Another option (with a little more hack value) would be to calculate the values from the boolean result of the condition. Negate the boolean value, cast it to an int and add 1 to it:
$var = [int](-not (<condition>)) + 1
In Powershell 7 you can use the ternary operator:
$x = $true ? 1 : 2
echo $x
displays 1.
What you may want however is switch, e.g.,
$in = 'test2'
$x = switch ($in) {
'test1' {1}
'test2' {2}
'test3' {4}
}
echo $x
displays 2.
A little example that can help to understand.
PowerShell script:
$MyNbr = 10
$MyMessage = "Crucial information: " + $(
if ($MyNbr -gt 10) {
"My number is greater than 10"
} elseif ($MyNbr -lt 10) {
"My number is lower than 10"
} else {
"My number is 10"
}
)
Write-Host $MyMessage
Output:
Crucial information: My number is 10
If you change the MyNbr variable, you will have a different result depending on conditions in the if statements.
You actually can evaluate a condition and assign the result to a variable. It's the closest you get to a ternary operator in PowerShell. I find it makes it simpler to do complicated conditional statements. It makes it easier to read and change them. Here's an example:
$theEventIdIWant = 6000
$eventId = 5000
$correct = $eventID -eq $theEventIdIWant
if($correct) {$true} else {$false}

Returning a Row Count for a DataRow in PowerShell

My script is populating a datarow from a stored procedure in SQL Server. I then reference specific columns in this datarow throughout the script. What I'm trying to do is add functionality that takes action X if the row count = 0, action Y if the row count = 1, and action Z if the row count > 1.
-- PowerShell script snippet
# $MyResult is populated earlier;
# GetType() returns Name=DataRow, BaseType=System.Object
# this works
ForEach ($MyRow In $MyResult) {
$MyFile = Get-Content $MyRow.FileName
# do other cool stuff
}
# this is what I'm trying to do, but doesn't work
If ($MyResult.Count -eq 0) {
# do something
}
ElseIf ($MyResult.Count -eq 1) {
# do something else
}
Else {
# do this instead
}
I can get $MyResult.Count to work if I'm using an array, but then I can't reference $MyRow.FileName directly.
This is probably pretty simple, but I'm new to PowerShell and object-oriented languages. I've tried searching this site, The Scripting Guy's blog, and Google, but I haven't been able to find anything that shows me how to do this.
Any help is much appreciated.
It has everything to do with how you populate $MyResult. If you query the database like
$MyResult = #( << code that returns results from database >> )
that is, enclosing the code that returns your dataset/datatable from the database within #( ... ), then number of rows returned will be easily checked using $MyResult.count.
Your original code should work as-is if you populate $MyResult this way.
I know this thread is old, but if someone else finds it on Google, this should work also on PS V5:
Replace $MyResult.Count with: ($MyResult | Measure-Object | select -ExpandProperty Count)
For Example:
If (($MyResult | Measure-Object | select -ExpandProperty Count) -eq 0)
I don't have experience with PS and SQL, but I'll try to provide an answer for you. If you're object $myresult is a datarow-object, it means you only got the one row. If the results are empty, then $myresult will usually be null.
If you get one or more rows, you can put them in an array and count it. However, if your $myresult are null, and you put it in an array it will still count as one, so we need to watch out for that. Try this:
If ($MyResult -eq $null) {
# do something if no rows
}
Else If (#($MyResult).Count -eq 1) {
# do something else if there are 1 rows.
# The cast to array was only in the if-test,
# so you can reach the object with $myresult.
}
Else {
# do this if there are multiple rows.
}
Looks like this question gets a lot of views, so I wanted to post how I handled this. :)
Basically, the fix for me was to change the method I was using to execute a query on SQL Server. I switched to Chad Miller's Invoke-SqlCmd2 script: TechNet: Invoke-SqlCmd2, i.e.
# ---------------
# this code works
# ---------------
# Register the function
. .\Invoke-Sqlcmd2.ps1
# make SQL Server call & store results to an array, $MyResults
[array]$MyResults = Invoke-Sqlcmd2 -Serve
rInstance "(local)" -Query "SELECT TOP 1 * FROM sys.databases;"
If ($MyResult -eq $null) {
# do something
}
ElseIf ($MyResult.Count -eq 1) {
# do something else
}
Else {
# do this instead
}

Powershell - Use multidimention arrays for storing data - Need suggestion

I'm googling since a while, but I didn't find a solution to my problem.
I have to say I'm newbie in Powershell.
I would like to create the following array
$a = (A,B,C,D) where
A = 1 string (always)
B = 1 string (always)
C = undefined number of strings. I need to be able to add elements dynamically
D = undefined number of strings. I need to be able to add elements dynamically (same number as C)
Is this possible?
Example of 2 elements of the array
("WSTM0123456", "192.168.10.155",("WSTM8765421","WSTM9856454","WSTM1289765"),("192.36.36.36", "187.25.25.25","192.69.89.65"))
("WLDN1251254", "156.25.36.54", ("WLDN1234512", "WLDN9865323"), ("187.154.12.12","163.136.25.98"))
I don't know a priori how many elements will be in C and D and I'll have to append strings in position C and D with a for cycle.
Scope: group many strings (C & D) under the same string (A/B) which are in common.
Any help would be appreciated
Thanks,
Marco
You can do this, but it's probably quite painful as dealing with arrays is sometimes cumbersome in PowerShell due to lots of implicit flattening.
I'd suggest creating a custom type for this. Then you can also give the individual parts useful names (I don't know the purpose of what you're doing here, so I'm making up names here. Feel free to change):
$properties = #{
Name = 'WSTM0123456';
IP = [ipaddress]'192.168.10.155';
ListOfNames = #("WSTM8765421","WSTM9856454","WSTM1289765");
ListOfIPs = [ipaddress[]]#("192.36.36.36", "187.25.25.25","192.69.89.65")
}
$foo = New-Object PSObject -Property #properties
Then you can simply append new items like so:
$foo.ListOfNames += 'AnotherName'
I think this is pretty much the same idea. Use a hash table, and make two of the elements arrays. This is how you would create the arrays "on the fly" at runtime, without knowing what any of the contents were going to be in advance, taking $x and putting any item that starts with "t" in "C" , and everything else in "D":
$a = #{A = "Some string";B = "Some other string"}
$x = "one","two","three","four","five"
$x |% {
if ($_ -match "^t"){$a["C"] += #($_)}
else {$a["D"] += #($_)}
}
$a.a
Some string
$a.b
Some other string
$a.c
two
three
$a.d
one
four
five
$obj = new-object psobject -property $a