Padding the iterator in a for loop - powershell

I'm trying to pad the iterator in a for loop using PowerShell, but I get an error message.
Normal padding works fine:
$mytext = "Test"
Write-Host $mytext.PadLeft(5, "0")
# Output: 0Test
But using the iterator doesn't work:
for ($i=1; $i -lt 20; $i++) {
Write-Host $i.PadLeft(2, "0")
}
Method invocation failed because [System.Int32] does not contain a method named 'PadLeft'.
Not even if I copy the iterator into a variable before padding:
for ($i=1; $i -lt 20; $i++) {
$Iterator = $i
Write-Host $Iterator.PadLeft(2, "0")
}
Method invocation failed because [System.Int32] does not contain a method named 'PadLeft'.
Is it impossible to use PadLeft() in a for loop at all?

Its because $i is an integer and as the error message tells you, it doesn't contain a PadLeft method. Anyway, you could cast the integer to a string:
for ($i=1; $i -lt 20; $i++) {
$Iterator = [string]$i
Write-Host $Iterator.PadLeft(2, "0")
}

Related

IndexOutOfRange

I'm getting this error:
Array assignment failed because index '3' was out of range.
At Z:\CSP\deploys\aplicacional\teste.ps1:71 char:12
+ $UNAME[ <<<< $i]= $line
+ CategoryInfo : InvalidOperation: (3:Int32) [], RuntimeException
+ FullyQualifiedErrorId : IndexOutOfRange
I really can't find why the index end there.
$CSNAME = #(KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:csname $SEARCH)
$UNAME = #()
$i = 0
Write-Host "Length="$CSNAME.Length
while($i -le $CSNAME.Length)
{
Write-Host "Start "$i
#$CSNAME[$i].GetType()
if ($CSNAME[0].StartsWith("OK:")) {
Write-Host "ACES $ACES does not exist" -Foreground "red"
}
if ($CSNAME[$i].StartsWith("OK:")) {
break
}
Write-Host "CSNAME="$CSNAME[$i]
$UNAME = $UNAME + $i
$UNAME = KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:UserName -ref-csname:$CSNAME[$i]
foreach ($line in $UNAME) {
if (! ($line.StartsWith("OK:"))) {
Write-Host $i
$UNAME = $UNAME + $i
Write-Host "uname var"$i
$UNAME[$i] = $line
} else {
Write-Host "break"
break
}
}
#$UNAME[$i].GetType()
#if ($UNAME[$i].StartWith("OK:*")){
# break
#}
Write-Host "UNAME="$UNAME[$i]
#$UNAME[$i]
Write-Host "End "$i
$i += 1
Write-Host "switch"
}
Since the second while is based in the first array length and it has values, why is the it getting out of range?
PowerShell arrays are zero-based, so an array of length 3 has index values from 0 through 2. Your code, however, would iterate from 0 to 3, because the loop condition checks if the variable is less or equal the length (-le):
while($i -le $CSNAME.Length)
{
...
}
You need to check if the variable is less than the length (or less or equal the length minus one):
while($i -lt $CSNAME.Length)
{
...
}
Also, you'd normally use a for loop for iterating over an array, so you can handle the index variable in one place:
for ($i=0; $i -lt $CSNAME.Length; $i++) {
...
}
Edit: You initialize $UNAME as an array, but inside the loop you assign $UNAME = KPScript ..., which replaces the array with whatever the script returns (another array, a string, $null, ...). Don't use the same variable for different things in a loop. Assign the script output to a different variable. Also, your way of appending to the array is rather convoluted. Instead of $UNAME = $UNAME + $i; $UNAME[$i] = $line simply do $UNAME += $line.
$res = KPScript -c:GetEntryString $PASSHOME\$PASSFILE -pw:$PASS -Field:UserName -ref-csname:$CSNAME[$i]
foreach ($line in $res) {
if (! ($line.StartsWith("OK:"))) {
$UNAME += $line
} else {
break
}
}

Method returning string but is assigned as string[]

I have this code:
[string]$emailBody = getEmailBody $firstName $emailTemplateFileContent
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i])
}
$emailTemplateText = $sb.ToString()
$emailTemplateTextCustomised = $emailTemplateText.Replace("#name", $firstName)
return $emailTemplateTextCustomised
}
When I type $emailTemplateTextCustomised.getType() I can see that it is a string.
However when I type $emailBody.getType() I can see that it is an Array.
I can also see that the array has 8 strings, each string containing the output from getEmailBody().
UPDATE:
Powershell seems really buggy, it is no longer a String[] but just a String with 8 repetitions of the output from getEmailBody().
Why is it doing this?
Thanks in advance.
PowerShell isn't buggy, well at least not in this case. :-) You have to understand that in PowerShell the "output" of a function is anything that is not captured to a variable. The line that does the StringBuilder.AppendLine() returns the StringBuilder and that is added to the output of your function. Try this:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString()
$emailTemplateText.Replace("#name", $firstName)
}
If you are on V3 (maybe V2) you can use the -replace operator as well:
function getEmailBody($firstName, $emailTemplateFileContent)
{
$sb = New-Object Text.StringBuilder
for ($i = 1; $i -lt $emailTemplateFileContent.Length; $i++)
{
$sb.AppendLine($emailTemplateFileContent[$i]) > $null
}
$emailTemplateText = $sb.ToString() -replace '#name',$firstName
$emailTemplateText
}

How to declare and get array value

I am new to Powershell, first time using it.
I have declared an array and use array value but using below code, I am not able to retrieve the array value...Any idea what I am missing here?
Just FYI.. I am executing script in ADOBE ILLUSTRATOR and for testing I am using 3 here in condition (for loop)... will use $array later
$array = "a.jpg","b.jpg","c.jpg";
for ($i=1; $i-le=3; $i++)
{
$.writeln("This is line number " + $array[$i]);
var targetFileName = $array[$i]+'.png';
$.writeln(targetFileName);
}
I tried $array[$i].toString() as well but still not getting values... I am getting 0
Any help is appreciated and thanks in advance to all for your help
for ($i=1; $i-le=3; $i++)
The condition in the above line doesn't have a valid comparison operator. Change that to
for ($i=1; $i -le 3; $i++)
if you want the loop to terminate after 3 cycles.
$.writeln("This is line number " + $array[$i]);
var targetFileName = $array[$i]+'.png';
$.writeln(targetFileName);
This is not valid PowerShell. Looks more like JavaScript to me. In PowerShell it should probably look like this:
Write-Output "This is line number $i"
$targetFileName = $array[$i] + '.png'
Write-Output $targetFileName
or shorter
"This is line number $i"
$array[$i] + '.png'
Note that PowerShell arrays are zero-based, so the last iteration ($array[3]) will return $null instead of an element from the array. If you want to iterate over the elements of the array you should change your loop to this:
for ($i=0; $i -lt $array.Length; $i++) {
"This is line number $($i+1)"
$array[$i] + '.png'
}
or (better) pipe your array into a foreach loop:
$i = 0
$array | % {
"This is line number " + ++$i
$_ + '.png'
}

Powershell - concatenating an array reference with another variable

I'm trying to concatenate a variable with a value from an array, and having problems.
The output I get is the variable value, plus the ENTIRE array, not just the desired value (index of $i).
$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
for ($i=0; $i -le $ExtractTables.Length – 1; $i++) {
write-host $Database$ExtractTables[$i] # <<<<<<< takes ENTIRE array
}
My ultimate goal is to call an executable (bcp) something like this:
# & bcp $Database$ExtractTables[$i] out $OutputDirectory$ExtractTables[$i].txt -c -T -SCHELDEV02
Any pointers for a newbie?
Thanks!
$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
for ($i=0; $i -le $ExtractTables.Length – 1; $i++) {
write-host "$Database$($ExtractTables[$i])"
}
To evaluate a sub-expression before the rest of the expression put it inside $()
$Database = "Checklist.dbo."
$ExtractTables = #("Page"
, "HotelOwner"
, "Hotel"
)
$ExtractTables | ForEach {
write-host "$Database$_"
}

Referencing Powershell array index produces unexpected results when referenced with string

I am trying to find out why the following occurs if you have
$arr = #("Filename1", "Filename2")
for($i =0; $i -le $arr.Length -1; $i++) {
write-host ".\"$arr[$i]
write-host ".\$arr[$i]"
write-host $arr[$i]
}
So taking just one loop through it produces:
".\ Filename1"
".\ Filename1 Filename2[0]"
"Filename1"
Just referencing the array[index] will produce the correct value, but if I concatenated with a string it places a space between the string and value. When placed within the string I assume it is dumping the entire contents because it is evaluating $array then evaluating $i ending up with
".\ filename1 filename2[index number]"
But if I assign the individual value to a separate variable and concatenate it with a string there is no space? Why is that:
Example:
$name = $arr[$i]
write-host ".\$name"
output = ".\filename1"
which is correct.
You have to do:
write-host ".\$($arr[$i])"
so that it is evaluated as array indexing.
It would be the case with something like accessing properties of an object or key of hash etc within the string:
PS > $a = #{test="A";test2="B"}
PS > write-host "$a.test"
System.Collections.Hashtable.test
PS > write-host "$($a.test)"
A
Another alternative is to use string formatting, especially useful when you have lots of variables / objects in the string:
write-host (".\{0}" -f $arr[$i])
Your code should look like this:
$arr = #("Filename1", "Filename2")
#for($i =0; $i -le $arr.Length-1; $i++) {
for($i =0; $i -le $arr.Length; $i++) {
write-host ".\"$arr[$i]
#write-host ".\$arr[$i]"
write-host ".\$($arr[$i])"
write-host $arr[$i]
}