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 inbetween?
thank you!
--EDIT-- I cannot post the whole code because it is stored on a VM and i cannot copy contents into my actual computer. But here is the part 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
CodePudding user response:
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 :)