Index was outside the bounds of the array error when processing .svd file - powershell

clear
# Powershell scripts used to mask Private Personal Information on data files.
# path to PERM file
$path = "MYURL\ABS.SVD"
# get file content
$content = Get-Content $path
$content | ForEach-Object {
$mask50 = 'X' * 50 # variables to makes fields by letter according to length
$mask30 = 'Y' * 30
$mask20 = 'A' * 20
$mask08 = 'Z' * 8
$mask05 = 'B' * 5
$mask16 = 'C' * 16
# if statement, if the string is at position 0-10, and begins with
# 'STARTDELIV' then run replace statement
if ($_.Substring(0,10) -eq 'STARTDELIV') {
$SplitString = $_.Split('|')
$SplitString[3] = $mask30 # Fields : To Fax Name
$SplitString[4] = $mask20 # Fields : To fax Number
$SplitString[9] = $mask50 # Fields : To EMail Address
$SplitString -join '|'
} else {
$_
}
} | Out-File "MYURL\ABS-Output.svd" -Encoding ASCII
I have a script which masked certain fields in a data file (fields seperated by '|'). I have done a lot of these and they work fine. However, when I copy this exact file to another folder to use a different data file (.svd) I get the "Index was outside the bounds of the array", I've seen a few other threads on this but none really answer my query.
Curious as to why it still works in a particular folder location but not the other (I am changing the input and output urls to direct to the new folder).
Error below:
Index was outside the bounds of the array.
AtMYURL-Masked-Fields.ps1:28 char:3
+ $SplitString[3] = $mask30 #To Fax Name
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], IndexOutOfRangeException
+ FullyQualifiedErrorId : System.IndexOutOfRangeException

Answer provided by #lit
"There is at least one record starting with STARTDELIV that does not have enough fields. find /I "STARTDELIV" "MYURL\ABS.SVD" "

Related

PowerShell - Replace a specific string in xml file

After debugging I saw that the version was changed but not saved
How can I save the changes for the CDATA?
I added this: Its ok? Should I need the [0]? or the Parent?
Now only the CDATA is affected.... The second part stays as is
$CDATANodes[0].ParentNode.OwnerDocument.Save($xmlFile.FullName)
I have xml file that contains version number. I know how to replace a string in a file but here I need to find something that start with 8 and replace it with a number.
For an example
There are many places where the version 8.5.34.31.4 is displayed (There are more that not located in nodes.
I need to search something like 8. and replace it with another number like 8.5.34.31.5
For every xml the version is different (8.5.34, 8.6.22,...) So I thought to search the common beginning that is 8
Any idea how to do this?
$ReleaseVersion = '8.5.34.31.6'
$xmlFilePath = 'C:\Temp\BuildDescription.xml'
function ChangeVersionForRelease ([string] $ReleaseVersion, [string] $xmlFilePath)
{
# define the new version number
#$newVersion = '8.5.34.31.5'
# locate document on disk
$xmlFile = Get-Item $xmlFilePath
# use Select-Xml to read, parse, and query document for relevant nodes
$targetNodes = $xmlFile |Select-Xml -XPath '//*[starts-with(text(), "8.")]'
if($targetNodes){
$targetNodes |ForEach-Object {
# replace the string contents of the node with the new version number
$_.Node.InnerText = $ReleaseVersion
}
$CDATANodes = $xmlFile | Select-Xml -XPath '//*/text()' | ForEach-Object Node | Where-Object NodeType -EQ 'CDATA'
Foreach($CDATANode in $CDATANodes){
$CDATANode.InnerText = $CDATANode.InnerText -replace '8(\.\d+)*',$ReleaseVersion
}
# save to disk after modifying
$targetNodes[0].Node.OwnerDocument.Save($xmlFile.FullName)
}
}
ChangeVersionForRelease $ReleaseVersion $xmlFilePath
All the nodes were replaced but not the CDATA. I got an exception
Select-Xml : Cannot convert value "C:\Temp\BuildDescription.xml" to type "System.Xml.XmlDocument". Error: "The specified node cannot be inserted as the valid child of this node, because the specified node is the
wrong type."
At line:21 char:30
$CDATANodes = $xmlFilePath | Select-Xml -XPath '//*/text()' | ForEach ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidArgument: (:) [Select-Xml], ParentContainsErrorRecordException
FullyQualifiedErrorId : InvalidCastToXmlDocument,Microsoft.PowerShell.Commands.SelectXmlCommand
I change from $xmlFilePath to $xmlFile and now I don't have an error but the replacement was not done. Maybe I don't save it?

PowerShell read column value from csv file [duplicate]

This question already has answers here:
How can you use an object's property in a double-quoted string?
(5 answers)
Closed 1 year ago.
This is my below input data which is in CSV format and roles,admin, accountant and security are columns.
roles, admin,accountant,security
Engineer, ,x , ,
I want to get value of rows using columns with below code, example , foreach for accountant column should return 'x', but I am getting something else.
$path = "$PSScriptRoot\Test.csv"
$csv = Import-Csv -path $path -Delimiter ","
$columns = $csv | Get-member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'
$csv | ForEach-Object {
$row = $_
foreach ($col in $columns) {
Write-Host " vaalue of scripting is : $col "
Write-Host " vaalue of scripting row is : $row.$col "
Start-Sleep -s 10
}
}
Output I get is
vaalue of scripting is : accountant
vaalue of scripting row is : #{roles=Engineer; admin=; accountant=x ; security=}.accountant
vaalue of scripting is : admin
vaalue of scripting row is : #{roles=Engineer; admin=; accountant=x ; security=}.admin
vaalue of scripting is : roles
vaalue of scripting row is : #{roles=Engineer; admin=; accountant=x ; security=}.roles
How can I get 'x' for accountant column or any other column value using
Following from my comment, short answer was to use the Subexpression operator $( ), which would allow PowerShell to reference the property $col of the object $row.
Short extract from MS Docs:
Use this when you want to use an expression within another expression. For example, to embed the results of command in a string expression.
To give you a short explanation of why this is needed, using this as an example:
$object = [pscustomobject]#{
foo = 'var'
}
$property = 'foo'
When we do "$object.$property" or in simple terms, "$object.foo", the double quotes "..." are not allowing PowerShell to reference the foo property from $object because the dot . is interpreted as literal and not as a dot method. In addition, the quotes are converting $object to its stringified ? representation #{foo=var} followed by the literal dot . followed by the variable expansion of $property.
Another extract from about_Properties:
The most common way to get the values of the properties of an object is to use the dot method. Type a reference to the object, such as a variable that contains the object, or a command that gets the object. Then, type a dot (.) followed by the property name.
Lastly, what other alternatives do we have to get around this besides $(...):
String Formatting and String.Format method:
'Value of $object.$property is "{0}".' -f $object.$property
[string]::Format('Value of $object.$property is "{0}".', $object.$property)
Using + to concatenate strings is also a very known one:
'Value of $object.$property is "' + $object.$property + '".'
As a side note, and unrelated to the actual issue, this might be a more direct way of approaching your code:
#'
roles,admin,accountant,security
Engineer,,x,,
Operator,,y,,
'# |
ConvertFrom-Csv | ForEach-Object -Begin { $i = 1 } -Process {
foreach($Property in $_.PSObject.Properties.Name)
{
'Value of Row {0} Column "{1}" is "{2}"' -f
$i, $Property, (
'NULL', ($val = $_.$Property)
)[[int][bool]$val]
}
$i++
}
Note the use of .PSObject to access the object's properties and methods, an alternative to Get-Member.
The above would result in:
Value of Row 1 Column "roles" is "Engineer"
Value of Row 1 Column "admin" is "NULL"
Value of Row 1 Column "accountant" is "x"
Value of Row 1 Column "security" is "NULL"
Value of Row 2 Column "roles" is "Operator"
Value of Row 2 Column "admin" is "NULL"
Value of Row 2 Column "accountant" is "y"
Value of Row 2 Column "security" is "NULL"
I wrote this based on your csv file, let me know if it worked (change the folder path and file name).
$folderspath = 'C:\Test'
$csvfilename = 'info.csv'
$csvfilepath = $folderspath + "\" + $csvfilename
$csvfilepath = $csvfilepath.ToString()
$csvfile = Import-CSV -Path $csvfilepath -Delimiter ","
ForEach ($row in $csvfile) {
IF($row.security -eq "High") {
$Roles = $row.roles
$Admin = $row."admin"
$Accountant = $row.accountant
$Security = $row."security"
Write-Host "Roles: " $Roles "; Admin:" $Admin "; Accountant:" $Accountant "; `
Security:" $Security
}
}
The csv file I used
roles, admin,accountant,security
Engineer, ,x , ,
Engineer2,Yes ,x ,High,
Engineer3, No, , Low,

Array index evaluated to null - Find linenumber and use it as index number

My input file looks like this:
#EXTM3U
#EXTI NF:-1 tvg-name="Das Erste HD" tvg-id="ARD.de" group-title="Vollprogramm" tvg-logo="https://raw.githubusercontent.com/jnk22/kodinerds-iptv/master/logos/tv/daserstehd.png",Das Erste HD
https://daserstehdde-lh.akamaihd.net/i/daserstehd_de#625196/index_2739_av-p.m3u8
#EXTINF:-1 tvg-name="Das Erste" tvg-id="ARD.de" group-title="Vollprogramm" tvg-logo="https://raw.githubusercontent.com/jnk22/kodinerds-iptv/master/logos/tv/daserste.png",Das Erste
https://daserstelive-lh.akamaihd.net/i/daserste_de#28289/index_3776_av-p.m3u8
..
I want to replace the stream with my variable $newRtsp and write it back to the file. What I currently have is:
# Getting the file
$inFile = Get-Content "iptv.m3u"
# Linenumber where a specific channel name $chanName exists
$line = ($inFile | Select-String "tvg-name=`"$chanName`"").LineNumber #`# dummy comment to fix code highlighting for SO
# Use actual Linenumber as Index, to override the following line
$inFile[$line] = $newRtsp
# Write back to file
$inFile | Set-Content "iptv.m3u"
Problem: Somehow, I can't use the found linenumber as index:
Index operation failed; the array index evaluated to null.
At E:\merge-fritzbox.ps1:17 char:5
+ $inFile[$line] = $newRtsp
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArrayIndex
The line number returned by Select-String starts counting from 1. Array indices count from 0, so you need to consider that.
This should work:
$chanName = "Das Erste HD"
$newRtsp = "the new content for the line"
# Getting the file
$inFile = Get-Content "iptv.m3u"
# Linenumber where a specific channel name $chanName perhaps exists?
# SimpleMatch is an optional parameter and specifies that
# the string in the pattern is not interpreted as a regular expression.
$line = ($inFile | Select-String "tvg-name=`"$chanName`"" -SimpleMatch).LineNumber #`# dummy comment to fix code highlighting for SO
# $line will be $null if Select-String did not find the string to look for
if ($line) {
# Use actual Linenumber minus 1 as Index, to override the following line
$inFile[$line - 1] = $newRtsp
# Write back to file
$inFile | Set-Content "iptv.m3u"
}

Powershell Adding items from text file to 2 dimensional array

I am used to coding in java and I am brand new to Powershell. I have a text file that contains Windows server info displayed like this.
14.0.3026.27,None,CU7,4229789,SQL Server 2017,0
14.0.3025.34,None,CU6,4101464,SQL Server 2017,0
14.0.3023.8,None,CU5,4092643,SQL Server 2017,0
I am trying to throw this info into a 2 dimensional array and want it to look like this.
[14.0.3026.27],[None],[CU7],[4229789],[SQL Server 2017],[0]
[14.0.3025.34],[None],[CU6],[4101464],[SQL Server 2017],[0]
[14.0.3023.8],[None],[CU5],[4092643],[SQL Server 2017],[0]
The code I have is giving this error message:
Cannot index into a null array. At line:9 char:9
+ $array[$i][$j] = $word
+ ~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : NullArray
Here is my code:
$file = Get-Content "C:\Users\UserName\Desktop\sqlServers.txt"
$array = #(), #()
$i = 0
$j = 0
foreach ($line in $file){
$j=0
foreach ($word in $line.split(",")){
$array[$i][$j] = $word
$j+=1
}
$i+=1
}
PowerShell (and .NET) arrays are fixed size so assigning to an element beyond the array bounds won't grow the array. Instead, let PowerShell build the arrays for you. The following will produce what you want (an array of arrays btw, not an actual 2-d array)
$result = get-content data.txt | foreach { , ($_ -split ',')}
In this code, reading the data will give you the rows, splitting the rows will give you the columns. The trick is the comma before the split operation. Without it, all of the elements would be streamed into a single flat array. The comma preserves the nested array so you get the desired array of arrays.
As your file is comma separated (it's a CSV with a .txt extension) you could instead use Import-Csv to create the array.
You will need to manually specify headers as you example input doesn't include them.
Code with example headers:
$array = Import-Csv "C:\folder\sqlServers.txt" -Header Version,Something,CU,Number,Product,Another
You can then reference the items by index and property name:
PS > $array[0].CU
CU7
PS > $array[2].Product
SQL Server 2017

Not able to call out array headers in a foreach loop

Okay - this is a really weird issue - and it probably has a really stupid solution.
But i import a csv
$csv = import-csv c:\users\hello.csv
Then i have an array of words, for which i am wanting to use to search through the csv - and if there's a match in the csv - populate an adjacent column in the csv.
here's the array:
$newhandles
hi
hello
now - if i run a foreach loop with an if statement inside of it - it doesn't recognize one of the headers.
foreach ($newhandle in $newhandles)
{if ($csv.name -eq $newhandle) {$csv.redundant = $newhandle}}
however it gives me this error:
The property 'redundant' cannot be found on this object. Verify that the property exists
and can be set.
At line:1 char:69
+ ... andles) {if ($csv.name -eq $newhandle) {$csv.redundant = $newhandle}}
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyAssignmentException
I know the property exists - because if i call it directly - it shows three empty slots - and if i call something to it directly - the element will populate. such as
> $csv[0].redundant = 'hi'
> $csv[0]
name : hi
description : don't settle
system : sight
redundant : hi
tags :
Any ideas?
try using this foreach loop :
foreach ($rec in $csv){
if($newhandles -contains $rec.name){
$rec.redundant = $rec.name
}
}
if you check ($csv.redundant).GetType(),you can see that it returns an array instead of the property you want but when you are assigning value to $csv[0].redundant you are accessing the exact property and that's why it works when you tested manually
try this
import-csv "c:\users\hello.csv" | select * , #{N="redundant";E={if ($newhandles -contains $_.Name) {$_.Name} else {$null}}} -ExcludeProperty redundant