Forum Discussion
Fred_Elmendorf
Jul 25, 2023Brass Contributor
How to use powershell to read the values in the 2nd and 18th columns of a csv file with no headers
I have a text file with a couple hundred lines of data where the data elements are separated by a comma. The lines of data have varying numbers of elements in each line, but I am only inter...
- Jul 26, 2023
Hi, Fred.
First of all, let me re-state your output here as I've interpreted it, as with all that line-wrapping in the original post, it's hard to be sure I have interpreted correctly:
Header=0,"Some Name",0,3,54,48,90,0,1,23,0,100,1,5,0.400000,250,1000,500,9600,10,10,10,960,1,2,30,14,100,1,5,0,0,2000,0,0,0,1,0,0 RmSetup=4310,1,1#2|0|3#4|3#4|3#4|3#4|3#4|5#6|0|0|3#4|0|3#4|3#4|8|0,10,100,0,0,1,70,1,1,0,0,5310,0,0 C1=AAAAAAEEXX,195.168.3.1,0,0,DSP C2=AAAAAAEEXX,195.168.3.2,1,0,DSP C3=AAAAAAEEXX,195.168.3.3,1,0,DSP A1="A123 (Name2 CTG#2) - Ia",c,600.000000,100.000000,0.000000,Ia,-1,-1,-1,0.000000 A2="B123 (Name2 CC CTG#2) - Ib",c,600.000000,100.000000,0.000000,Ib,-1,-1,-1,0.000000
Let's assume I've interpreted the sample data correctly and move on.
First, since you have no header, that rules out Import-Csv. You can invest time in dynamically constructing a header but that's a waste of time and effort in this scenario.
Not using Import-Csv is fine for a second reason, which is you only care about the first line anyway, and Import-Csv doesn't allow you to read just one line - you have to read the whole file and then use client-side filtering to deal with just the first line, which is quite inefficient anyway.
So, what should we use instead?
Get-Content, as Get-Content addresses both requirements:
- Read content without a header;
- Read just a part of the file (in this scenario, just the first line).
Once we read the first line, we can split it up into its components and output the columns you're after.
Here's an example using your data sample:
Get-Content -Path "D:\Data\Temp\Forum\forum.csv" -TotalCount 1 | ForEach-Object { if (($Columns = $_.Split(",")).Count -ge 19) { [PSCustomObject] @{ # Remember, arrays are zero-based, so the second column has an index of 1, not 2. Column1 = $Columns[1]; Column18 = $Columns[18]; } } }
Sample output:
Cheers,
Lain
LainRobertson
Jul 26, 2023Silver Contributor
Hi, Fred.
First of all, let me re-state your output here as I've interpreted it, as with all that line-wrapping in the original post, it's hard to be sure I have interpreted correctly:
Header=0,"Some Name",0,3,54,48,90,0,1,23,0,100,1,5,0.400000,250,1000,500,9600,10,10,10,960,1,2,30,14,100,1,5,0,0,2000,0,0,0,1,0,0
RmSetup=4310,1,1#2|0|3#4|3#4|3#4|3#4|3#4|5#6|0|0|3#4|0|3#4|3#4|8|0,10,100,0,0,1,70,1,1,0,0,5310,0,0
C1=AAAAAAEEXX,195.168.3.1,0,0,DSP
C2=AAAAAAEEXX,195.168.3.2,1,0,DSP
C3=AAAAAAEEXX,195.168.3.3,1,0,DSP
A1="A123 (Name2 CTG#2) - Ia",c,600.000000,100.000000,0.000000,Ia,-1,-1,-1,0.000000
A2="B123 (Name2 CC CTG#2) - Ib",c,600.000000,100.000000,0.000000,Ib,-1,-1,-1,0.000000
Let's assume I've interpreted the sample data correctly and move on.
First, since you have no header, that rules out Import-Csv. You can invest time in dynamically constructing a header but that's a waste of time and effort in this scenario.
Not using Import-Csv is fine for a second reason, which is you only care about the first line anyway, and Import-Csv doesn't allow you to read just one line - you have to read the whole file and then use client-side filtering to deal with just the first line, which is quite inefficient anyway.
So, what should we use instead?
Get-Content, as Get-Content addresses both requirements:
- Read content without a header;
- Read just a part of the file (in this scenario, just the first line).
Once we read the first line, we can split it up into its components and output the columns you're after.
Here's an example using your data sample:
Get-Content -Path "D:\Data\Temp\Forum\forum.csv" -TotalCount 1 |
ForEach-Object {
if (($Columns = $_.Split(",")).Count -ge 19)
{
[PSCustomObject] @{
# Remember, arrays are zero-based, so the second column has an index of 1, not 2.
Column1 = $Columns[1];
Column18 = $Columns[18];
}
}
}
Sample output:
Cheers,
Lain
- Fred_ElmendorfJul 26, 2023Brass ContributorThank you, Lain!
Your solution gets just what I need.