Selecting columns from flat file in power shell with no column name - powershell

I am new to power shell ,and I have the below format (pipe delimiter) with no column name:
01|1|06/28/2017 00:00:00|06/28/2017 00:00:00
I want to choose the third or any column from this format,I have tried the below code :
$columns=(Get-Content $filepath | Out-String | select -Skip 2 -First 1).Split("|")
but it is not working can any one help please.

Use Import-CSV with -Header and -Delimiter specified; that way, you get a structure (PSCustomObject[]) with attributes that you can reference directly and meaningfully. For example,
$EntryList = Import-CSV -Path $FilePath -Header ID,Type,StartTime,EndTime -Delimiter '|'
gets you an array of PSCustomObjects, where each object has the indicated fields. You can then (for example) refer to $EntryList[$n].ID, $EntryList[$n].StartTime, and so on.

Related

Using Powershell, how can I export and delete csv rows, where a particular value is *not found* in a *different* csv?

I have two files. One is called allper.csv
institutiongroup,studentid,iscomplete
institutionId=22343,123,FALSE
institutionId=22343,456,FALSE
institutionId=22343,789,FALSE
The other one is called actswithpersons.csv
abc,123;456
def,456
ghi,123
jkl,123;456
Note: The actswithpersons.csv does not have headers - they are going to be added in later via an excel power query so don't want them in there now. The actswithpersons csv columns are delimited with commas - there are only two columns, and the second one contains multiple personids - again Excel will deal with this later.
I want to remove all rows from allper.csv where the personid doesn't appear in actswithpersons.csv, and export them to another csv. So in the desired outcome, allper.csv would look like this
institutiongroup,studentid,iscomplete
institutionId=22343,123,FALSE
institutionId=22343,456,FALSE
and the export.csv would look like this
institutiongroup,studentid,iscomplete
institutionId=22343,789,FALSE
I've got as far as the below, which will put into the shell whether the personid is found in the actswithpersons.csv file.
$donestuff = (Get-Content .\ActsWithpersons.csv | ConvertFrom-Csv); $ids=(Import-Csv .\allper.csv);foreach($id in $ids.personid) {echo $id;if($donestuff -like "*$id*" )
{
echo 'Contains String'
}
else
{
echo 'Does not contain String'
}}
However, I'm not sure how to go the last step, and export & remove the unwanted rows from allper.csv
I've tried (among many things)
$donestuff = (Get-Content .\ActsWithpersons.csv | ConvertFrom-Csv);
Import-Csv .\allper.csv |
Where-Object {$donestuff -notlike $_.personid} |
Export-Csv -Path export.csv -NoTypeInformation
This took a really long time and left me with an empty csv. So, if you can give any guidance, please help.
Since your actswithpersons.csv doesn't have headers, in order for you to import as csv, you can specify the -Header parameter in either Import-Csv or ConvertFrom-Csv; with the former cmdlet being the better solution.
With that said, you can use any header name for those 2 columns then filter by the given column name (ID in this case) after your import of allper.csv using Where-Object:
$awp = (Import-Csv -Path '.\actswithpersons.csv' -Header 'blah','ID').ID.Split(';')
Import-Csv -Path '.\allper.csv' | Where-Object -Property 'Studentid' -notin $awp
This should give you:
institutiongroup studentid iscomplete
---------------- --------- ----------
institutionId=22343 789 FALSE
If you're looking to do it with Get-Content you can split by the delimiters of , and ;. This should give you just a single row of values which you can then compare the entirety of variable ($awp) using the same filter as above which will give you the same results:
$awp = (Get-Content -Path '.\actswithpersons.csv') -split ",|;"
Import-Csv -Path '.\allper.csv' | Where-Object -Property 'Studentid' -notin $awp

Remove String from Character from column in CSV using Powershell

I have a CSV file containing two columns:server name with domain and date
servername.domain.domain.com,10/15/2018 6:28
servername1.domain.domain.com,10/13/2018 7:28
I need to remove the fully qualified name so it only has the shortname and I need to keep the second column so it looks as is like below either by sending to a new CSV or somehow removing the domain inplace somehow. Basically I want the second column untouched but I need it to be included when creating a new CSV with the altered column 1.
servername,10/15/2018 6:28
servername1,10/13/2018 7:28
I have this:
Import-Csv "filename.csv" -Header b1,b2 |
% {$_.b1.Split('.')[0]} |
Set-Content "filename1.csv"
This works great, but the problem is the new CSV is missing the 2nd column. I need to send the second column to the new CSV file as well.
Use a calculated property to replace the property you want changed, but leave everything else untouched:
Import-Csv 'input.csv' -Header 'b1', 'b2' |
Select-Object -Property #{n='b1';e={$_.b1.Split('.')[0]}}, * -Exclude b1 |
Export-Csv 'output.csv' -NoType
Note that you only need to use the parameter -Header if your CSV data doesn't already have a header line. Otherwise you should remove the parameter.
If your input file doesn't have headers and you want to create the output file also without headers you can't use Export-Csv, though. Use ConvertTo-Csv to create the CSV text output, then skip over the first line (to remove the headers) and write the rest to the output file with Set-Content.
Import-Csv 'input.csv' -Header 'b1', 'b2' |
Select-Object -Property #{n='b1';e={$_.b1.Split('.')[0]}}, * -Exclude b1 |
ConvertTo-Csv -NoType |
Select-Object -Skip 1 |
Set-Content 'output.csv'

Use Import-Csv to read changable column Titles by location

I'm trying to see if there is a way to read the column values in a csv file based on the column location. The reason for this is the file I'm being handed always has it's titles being changed...
For example, lets say csv file column A (via excel) looks like the following:
ColumnOne
ValueOne
ValueTwo
ValueThree
Now the user changes the title:
Column 1
ValueOne
ValueTwo
ValueThree
Now I want to create an array of the first column. Normally what I do is the following:
$arrayFirstColumn = Import-Csv 'C:\test\test1.csv' | where-object {$_.ColumnOne} | select-object -expand 'ColumnOne'
However, as we can see if ColumnOne is changed to Column 1, it breaks this code. How can I create this array to allow an interchangeable column title, but the column location will always be the same?
You can specify headers of your own on import:
Import-Csv 'C:\path\to\your.csv' -Header 'MyHeaderA','MyHeaderB',...
As long as you don't export the data back to a CSV (or don't require the original headers to be in the output CSV as well) you can use whatever names you like. You can also specify as many header names as you like. If their number is less than the number of the columns in the CSV the additional columns will be omitted, if it's greater then the columns for the additional headers will be empty.
If you need to preserve the original headers you could get the header name(s) you need to work with in variable(s) like this:
$csv = Import-Csv 'C:\test\test1.csv'
$firstCol = $csv | Select-Object -First 1 | ForEach-Object {
$_.PSObject.Properties | Select-Object -First 1 -Expand Name
}
$arrayFirstColumn = $csv | Where-Object {$_.$firstCol} |
Select-Object -Expand $firstCol
Or you could simply read the first line from the CSV and split it to get an array with the headers:
$headers = (Get-Content 'C:\test\test1.csv' -TotalCount 1) -split ','
$firstCol = $headers[0]
One option:
$ImportFile = 'C:\test\test1.csv'
$FirstColumn = ((Get-Content $ImportFile -TotalCount 2 | ConvertFrom-Csv).psobject.properties.name)[0]
$FirstColumn
$arrayFirstColumn = Import-Csv $ImportFile | where-object {$_.$FirstColumn} | select-object -expand $FirstColumn
If you are using PowerShell v2.0 then the expression for $FirstColumn in $mjolinor's answer would be:
$FirstColumn = ((Get-Content $ImportFile -TotalCount 2 | ConvertFrom-Csv).psobject.properties | ForEach-Object {$_.name})[0]
(Apologies for starting a new answer; I do not yet have enough reputation to add a comment to mjolinor's post)

How to select the first 10 columns of a headerless csv file using PowerShell?

I have a CSV file called test.csv ($testCSV).
There are many columns in this file but I would simply like to select the first 10 columns and put these 10 columns in to another CSV file.
Please note that I DO NOT HAVE ANY COLUMN HEADERS so can not select columns based on a column name.
The below line of code will get the first 10 ROWS of the file:
$first10Rows = Get-Content $testCSV | select -First 10
However I need all the data for the first 10 COLUMNS and I am struggling to find a solution.
I have also had a look at splitting the file and attempting to return the first column as follows:
$split = ( Get-Content $testCSV) -split ','
$FirstColumn = $split[0]
I had hoped the $split[0] would return the entire first column but it only returns the very first field in the file.
Any help in solving this problem is very much appreciated.
Thanks in advance.
******UPDATE******
I am using the method as answered below by vonPryz to solve this problem, i.e.:
Import-Csv -Delimiter "," -Header #("a","b","c") -Path $testCSV | Select a,b
However I am now also trying to import the CSV file only where column b is not null by adding this extra bit of code:
Import-Csv -Delimiter "," -Header #("a","b","c") -Path $testCSV | Select a,b | where b -notmatch $null
I need to do this to speed up the script as there are tens of thousands of lines where column b is null and I do not need to import these lines.
However, the above code returns no data, either meaning the code must be wrong or it thinks the field b is not null. An example of 2 lines of the text file is:
1,2,3
x,,z
And I only want the line(s) where the second column is occupied.
I hope I've explained that well and again, any help is appreciated.
*******************ANSWER********************
Import-Csv -Delimiter "," -Header #("a","b","c") -Path $testCSV | Select a,b | Where-Object { $_.b -ne '' }
Thanks!
Lack of column headers is no problem. The cmdlet Import-CSV can specify headers with -Header switch. Assuming test data is saved as C:\temp\headerless.csv and contains
val11,val12,val13,val14
val21,val22,val23,val24
val31,val32,val33,val34
Importing it as CSV is trivial:
Import-Csv -Delimiter "," -Header #("a","b","c","d") -Path C:\temp\headerless.csv
#Output
a b c d
- - - -
val11 val12 val13 val14
val21 val22 val23 val24
val31 val32 val33 val34
Selecting just columns a and b is not hard either:
Import-Csv -Delimiter "," -Header #("a","b","c","d") -Path C:\temp\headerless.csv | select a,b | ft -auto
#Output
a b
- -
val11 val12
val21 val22
val31 val32
To start I want to mention that vonPryz's answer is a superb way of dealing with this. I just wanted to chime in about what you were trying to do and why it was not working.
You had the right idea. You were splitting the data on commas. However you were not doing this on every line. Just the file as a whole which was the source of your woes.
Get-Content $testCSV | ForEach-Object{
$split = $_ -split ","
$FirstColumn = $split[0]
}
That would split each line individually and then you could have populated the $FirstColumn variable.

Manipulate CSV files with Powershell (generate column for hashkey)

I have a CSV file with about 10 columns separated with a ; (semicolon). I would like to add another column which generates a hashkey for the first columns value.
Is there a possibility in Powershell to do this? Also are there short haskeys (up to 10 to 15 chars)?
Example:
Old:
10000;value2;value3....
New:
HashkeyOf10000;1000;value2;value3...
You can use a calculated property for adding a column to a CSV:
$csv = 'C:\path\to\your.csv'
(Import-Csv $csv -Delimiter ';') |
select -Property #{n='Hashkey';e={Calc-Hash $_.A}},* |
Export-Csv $csv -Delimiter ';' -NoType
Replace Calc-Hash with the actual name of your hash function and A with the actual name of the first column of your CSV.
The parentheses around Import-Csv are required to ensure that reading the file is completed before writing the output starts.