Powershell - Remove space between two variables - powershell

I have two array's which contain a selection of strings with information taken from a text file. I then use a For Loop to loop through both arrays and print out the strings together, which happen to create a folder destination and file name.
Get-Content .\PostBackupCheck-TextFile.txt | ForEach-Object { $a = $_ -split ' ' ; $locationArray += "$($a[0]):\$($a[1])\" ; $imageArray += "$($a[2])_$($a[3])_VOL_b00$($a[4])_i000.spi" }
The above takes a text file, splits it into separate parts, stores some into the locationArray and other information in the imageArray, like this:
locationArray[0] would be L:\Place\
imageArray[0] would be SERVERNAME_C_VOL_b001_i005.spi
Then I run a For Loop:
for ($i=0; $i -le $imageArray.Length - 1; $i++)
{Write-Host $locationArray[$i]$imageArray[$i]}
But it places a space between the L:\Place\ and the SERVERNAME_C_VOL_b001_i005.spi
So it becomes: L:\Place\ SERVERNAME_C_VOL_b001_i005.spi
Instead, it should be: L:\Place\SERVERNAME_C_VOL_b001_i005.spi
How can I fix it?

Option #1 - for best readability:
{Write-Host ("{0}{1}" -f $locationArray[$i], $imageArray[$i]) }
Option #2 - slightly confusing, less readable:
{Write-Host "$($locationArray[$i])$($imageArray[$i])" }
Option #3 - more readable than #2, but more lines:
{
$location = $locationArray[$i];
$image = $imageArray[$i];
Write-Host "$location$image";
}

Related

Powershell - output a foreach loop to one line

I am trying to take the output of my foreach loop and apply the array to a string that reads on one line. Here is my code so far:
$upper = 65..90
$lower = 97..122
foreach ($i in $upper)
{
[char]$i
}
foreach ($i in $lower)
{
[char]$i
}
I'm guessing I need to convert the output of the scriptblock to a variable and use the -join option, but everywhere I look I'm struggling to find how to structure that. Any guidance would be appreciated.
For this particular case, ForEach(type convertToType) is very useful, here is a cool way to get your lower and upper case dictionary string:
$lowerDict = [string]::new(([int][char]'a'..[int][char]'z').ForEach([char]))
$upperDict = $lowerDict.ToUpper()
If you have access to PowerShell Core, it can be reduced to:
$lowerDict = [string]::new('a'..'z')
$upperDict = $lowerDict.ToUpper()
As for what you are struggling on, how to do it with what you currently have (a foreach loop). You can capture all the output from the loop first:
$upper = foreach ($i in 65..90) { [char]$i }
Now, $upper is an array of chars, then to convert it to string, you can either use -join (guessed right) or [string]::new(...) as I did on my previous example:
$upperDict = -join $upper
# OR
$upperDict = [string]::new($upper)

PowerShell split input and replace/combine?

I want to be able to automatically generate an output if I run a PowerShell script that splits the input by a period "." and adds "DC=" in each item/object that has been split.
$DomainFQDN = "prod.mydomain.com" # This varies depending on the input. It could be "prod.boston.us.mydomain.com" as the input.
$DistinguishedName = $DomainFQDN -split "\."
...
...
...I just don't know how to proceed
How do I get an output of "DC=prod,DC=mydomain,DC=com" for prod.mydomain.com as the input or DC=prod,DC=boston,DC=us,DC=mydomain,DC=com for prod.boston.us.mydomain.com?
Well, you can use foreach construct with $DistinguishedName and use -join like this (if you want to output directly the joined string):
$AddDC = foreach ($e in $DistinguishedName) { "DC=$e" }
Write-Host $($AddDC -join ",")
-join works like -split, you just specify the character that you need to join by.
Other way to do it is to store $AddDC
$AddDC = foreach ($e in $DistinguishedName) { "DC=$e" }
$new_string = $AddDC -join ","
Write-Host $new_string
You can consult this page for more info.
If I got it right, this is what needed:
$fqdn='prod.boston.us.mydomain.com'
$dn="DC=$($fqdn.replace('.',',DC='))"
$dn
$DomainFQDN = "prod.mydomain.com"
$DomainFQDN = $DomainFQDN.Split(".")
For ($i = 0; $i -lt $DomainFQDN.Count; $i++) {
$DomainFQDN[$i] = "DC=" + $DomainFQDN[$i]
}
$DomainFQDN = $DomainFQDN -join ","
Write-Host $DomainFQDN
Output:
DC=prod,DC=mydomain,DC=com
I'm not sure why I couldn't get the -Split "." operator to work. It should function the same as .Split(".") but for some reason it gives a different result. But anyway this should work for you.
I feel like I should mention that a real FQDN would not be DC= on every line. It would look more like:
DC=Com,DC=MyDomain,OU=Prod
I usually do a single replace operation in an expandable to convert from FQDN to distinguished name of the domain root:
$DistinguishedName = "DC=$($DomainFQDN.TrimEnd('.') -replace '\.',',DC=')"
The TrimEnd('.') call strips any dot from rooted FQDNs, and the replace operation replaces each remaining dot with ,DC=

PowerShell Compare-Object, results in context

I'm using Compare-Object in PowerShell to compare two XML files. It adequately displays the differences between the two using <= and =>. My problem is that I want to see the difference in context. Since it's XML, one line, one node, is different, but I don't know where that lives in the overall document. If I could grab say 5 lines before and 3 lines after it, it would give me enough information to understand what it is in context. Any ideas?
You can start from something like this:
$a = gc a.xml
$b = gc b.xml
if ($a.Length -ne $b.Length)
{ "File lenght is different" }
else
{
for ( $i= 0; $i -le $a.Length; $i++)
{
If ( $a[$i] -notmatch $b[$i] )
{
#for more context change the range i.e.: -2..2
-1..1 | % { "Line number {0}: value in file a is {1} - value in file b {2}" -f ($i+$_),$a[$i+$_], $b[$i+$_] }
" "
}
}
}
Compare-Object comes with an IncludeEqual parameter that might give what you are looking for:
[xml]$aa = "<this>
<they>1</they>
<they>2></they>
</this>"
[xml]$bb = "<this>
<they>1</they>
<they>2</they>
</this>"
Compare-Object $aa.this.they $bb.this.they -IncludeEqual
Result
InputObject SideIndicator
----------- -------------
1 ==
2 =>
2> <=

Error with Substring Code - Powershell

I'm getting errors with the code below. I'm trying to take lines in a text file that are over 180 characters and parse them to a new line. I have to take the first 22 characters and put it in from of part two since it contains inital data that's needed on the line:
$data = get-content "C:\TestFile.txt"
$strAcct= #()
$strPart1= #()
$strPart2= #()
$strLength= #()
foreach($line in $data)
{
if ( $line.length -gt 181)
{ $strLength = $line.length
$strAcct += $line.substring(0,22)
$strPart1 += $line.substring(0,180)
$strPart2 += $line.substring(181,$strLength)
Add-Content "C:\TestFile-Output.txt" $strPart1
Add-Content "C:\TestFile-Output.txt" $strAcct $strPart2
}
Else {
Add-Content "C:\TestFile-Output.txt" $line
}
}
Substring takes an index, and the number of characters to take starting from that index. Your third substring bombs, because you are trying to take more characters than there are in the string. Change it to $strLength - 181, or alternatively, you can leave the second parameter out entirely, to just take the rest of the string starting from the index in the first parameter.
Change this:
$line.substring(181, $strLength)
to this:
$line.substring(181)
or even this:
$line.substring(181, $strLength - 181)

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]
}