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)
Related
I have seen this post:
Add-Content - append to specific line
But I cannot add these lines because "Array index is out of range".
What my script is doing:
Find the line
Loop through the array that contains the data i want to add
$file[$line]+=$data
$line+=1
Write to file
Should I create a new file content and then add each line of the original file to it?
IF so, do you know how to do that and how to stop and add my data in between?
Here is the part of my code where I try to add:
$f=Get-Content $path
$ct=$begin+1 #$begin is the line where I want to place content under
foreach($add in $add_to_yaml)
{
$f[$ct]+=$add
$ct+=1
}
$f | Out-File -FilePath $file
Let's break down your script and try to analyze what's going on:
$f = Get-Content $path
Get-Content, by default, reads text files and spits out 1 string per individual line in the file. If the file found at $path has 10 lines, the resulting value stored in $f will be an array of 10 string values.
Worth noting is that array indices in PowerShell (and .NET in general) are zero-based - to get the 10th line from the file, we'd reference index 9 in the array ($f[9]).
That means that if you want to concatenate stuff to the end of (or "under") line 10, you need to specify index 9. For this reason, you'll want to change the following line:
$ct = $begin + 1 #$begin is the line where i want to place content under
to
$ct = $begin
Now that we have the correct starting offset, let's look at the loop:
foreach($add in $add_to_yaml)
{
$f[$ct] += $add
$ct += 1
}
Assuming $add_to_yaml contains multiple strings, the loop body will execute more than once. Let's take a look at the first statement:
$f[$ct] += $add
We know that $f[$ct] resolves to a string - and strings have the += operator overloaded to mean "string concatenation". That means that the string value stored in $f[$ct] will be modified (eg. the string will become longer), but the array $f itself does not change its size - it still contains the same number of strings, just one of them is a little longer.
Which brings us to the crux of your issue, this line right here:
$ct += 1
By incrementing the index counter, you effectively "skip" to the next string for every value in $add_to_yaml - so if the number of elements you want to add exceeds the number of lines after $begin, you naturally reach a point "beyond the bounds" of the array before you're finished.
Instead of incrementing $ct, make sure you concatenate your new string values with a newline sequence:
$f[$ct] = $f[$ct],$add -join [Environment]::Newline
Putting it all back together, you end up with something like this (notice we can discard $ct completely, since its value is constant an equal to $begin anyway):
$f = Get-Content $path
foreach($add in $add_to_yaml)
{
$f[$begin] = $f[$begin],$add -join [Environment]::Newline
}
But wait a minute - all the strings in $add_to_yaml are simply going to be joined by newlines - we can do that in a single -join operation and get rid of the loop too!
$f = Get-Content $path
$f[$begin] = #($f[$begin];$add_to_yaml) -join [Environment]::Newline
$f | Out-File -FilePath $file
Much simpler :)
I am trying to replace everything in a string after a certain expression is found: In this case ",=dc".
Im kinda new to PowerShell so would appreciate any help. My code only replaces any ",=dc" but not what is behind that
$array += #()
$array += "vu=doc,vu=noc,dc=zet,dc=zez"
$array += "vu=doc,vu=nud,dc=gut,dc=zrt"
$array += "vu=doc,vu=nud,vu=dit,dc=gut,dc=zrt,dc=opt"
foreach ($value in $array){
$arraytype -replace "(?<=(,=dc)).*"
}
I want to only get back the "vu=doc,vu=noc"-part. Everything after the first ",=dc" should be deleted.
It's easier to use an indexed loop if you want the values in the array updated. Also, You can define an array simply by using a comma between the elements. Avoid concatenating with += as this means every time the entire array needs to be recreated in memory, which is both time and memory consuming.
Try
$array = "vu=doc,vu=noc,dc=zet,dc=zez",
"vu=doc,vu=nud,dc=gut,dc=zrt",
"vu=doc,vu=nud,vu=dit,dc=gut,dc=zrt,dc=opt"
for ($i = 0; $i -lt $array.Count; $i++) {
$array[$i] = ($array[$i] -replace 'dc=[^,]+,?').TrimEnd(",")
}
$array
Result:
vu=doc,vu=noc
vu=doc,vu=nud
vu=doc,vu=nud,vu=dit
Regex details:
dc= Match the character string “dc=” literally (case insensitive)
[^,] Match any character that is NOT a “,”
+ Between one and unlimited times, as many times as possible, giving back as needed (greedy)
, Match the character “,” literally
? Between zero and one times, as many times as possible, giving back as needed (greedy)
You can use IndexOf method to find the position of the string and use Substring method to slice the string up to that position.
$array = #()
$array += "vu=doc,vu=noc,dc=zet,dc=zez"
$array += "vu=doc,vu=nud,dc=gut,dc=zrt"
$array += "vu=doc,vu=nud,vu=dit,dc=gut,dc=zrt,dc=opt"
foreach ($value in $array){
$index = $value.IndexOf(",dc=")
if($index -eq -1) {
Write-Output $value
} else {
Write-Output $value.Substring(0, $index)
}
}
Note: I think you have a typo in the first line($array = #())
I can get the individual lines of a text file in powershell by indexing surround them with quotes by sub-expression
$textFile = Get-Content "myText.txt"
$i = 0
"$($textFile[$i])"
This will output the first line from the test file. But when I try to increment the index, it's not being passed to the variable when I call it, and still outputs the first line.
$i++ # value is now 1
"$($textFile[$i])" # value is still at the first index
$i++ # value is now 2
"$($textFile[$i])" # value is still at the first index
$i++ # value is now 3
"$($textFile[$i])" # value is still at the first index
The reason I'm keeping the variable in quotes is because that one line of the text file part of a bigger string that I can execute
while ($i -lt $textFile.count)
{
$remote = "Enter-PSSession -ComputerName`", $(textFile[$i])"
Invoke-Expression $remote
$global:i++
}
Thanks
I Was able to produce the desired outcome by using a foreach loop instead of a while loop:
foreach ($line in $textFile)
{
$remote = "Enter-PSSession -ComputerName`" $line"
Invoke-Expression $remote
}
I am reading in a text file that contains a specific format of numbers. I want to figure out if the first character of the line is a 6 or a 4 and store the entire line in an array for use later. So if the line starts with a six add the entire line into sixArray and if the line starts with a 4 add the entire line into fourArray.
How can I check the first character and then grab the remaining X characters on that line? Without replacing any of the data?
Something like this would probably work.
$sixArray = #()
$fourArray = #()
$file = Get-Content .\ThisFile.txt
$file | foreach {
if ($_.StartsWith("6"))
{
$sixArray += $_
}
elseif($_.StartsWith("4"))
{
$fourArray += $_
}
}
If you're running V4:
$fourArray,$sixArray =
((get-content $file) -match '^4|6').where({$_.startswith('4')},'Split')
Use:
$Fours = #()
$Sixes = #()
GC $file|%{
Switch($_){
{$_.StartsWith("4")}{$Fours+=$_}
{$_.StartsWith("6")}{$Sixes+=$_}
}
}
If it's me I'd just use a regex.
A pattern like this will catch everything you need.
`'^[4|6](?<Stuff>.*)$'`
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";
}