Replace string in an imported CSV file - powershell

I need to import a CSV file and then replace full usernames domain\username with username.
The following lines work but I only receive the amended usernames as the output and not the full file.
Could you please advise?
$TestFile = Import-Csv .\file.csv
$NewFile = $TestFile | ForEach-Object {$_."Username" -replace 'domain\\',''}

When processing CSV input with a ForEach-Object loop you need to output the data back to the pipeline. Also, the -replace operator doesn't modify variables or properties in-place. It takes the value, does the work, and outputs the modified string to the success output stream. If you want to update a property you need to assign the modified value back to that property.
Change this:
$TestFile = Import-Csv .\file.csv
$NewFile = $TestFile | ForEach-Object {$_."Username" -replace 'domain\\',''}
into this:
$NewFile = Import-Csv .\file.csv | ForEach-Object {
$_.Username = $_.Username -replace 'domain\\', '' # update username
$_ # feed data back into the pipeline
}
and the code will do what you want.

You can perform the replace on the string data, then convert it into an object using ConvertFrom-Csv.
$TestFile = (Get-Content .\file.csv) -replace 'domain\\',''
$NewFile = ConvertFrom-Csv $TestFile

Here's one way - get the column names from the input table, iterate each row in the table, and output new custom objects with needed changes.
$table = Import-Csv "Test.csv"
# Get column names
$columnNames = ($table | Select-Object -First 1).PSObject.Properties |
Select-Object -ExpandProperty Name
# Iterate each row in the table
foreach ( $row in $table ) {
$outputObject = New-Object PSObject
foreach ( $columnName in $columnNames ) {
if ( $columnName -eq "Username" ) {
$outputObject | Add-Member NoteProperty "Username" ($row.Username.Split('\')[1])
}
else {
$outputObject | Add-Member NoteProperty $columnName $row.$columnName
}
}
$outputObject
}
To create a new CSV file as output, put the above code in a script and pipe to Export-Csv.

Related

how to add extra ';'(semi colon) or any special character in all columns except first column and empty cell value from csv using powershell

I am using below code to add extra special character on all column except first column and empty cell value but code isn't working yet.
$path = 'F:\temp.csv'
Import-Csv $path | ForEach-Object {
if ($_.value -eq $path.value ) {
$_.value = ';'+$path.value
}
$_
} | Export-Csv $path -NoTypeInformation
Please see Image for more details:
Image
Please find csv file uploaded on Google Drive:
CSV FILE
I'm not sure what you were trying to do with $a, but if we remove that seems like you were close :)
Instead of checking if a value equals something we will just take every object and add a new property (i.e., a new column) to the object. We will call it 'B' and make the value the same as what's in 'A' but prefix a ';' to it using -replace. This replace operator uses regex so if we specify that we would like to replace '^', we are saying we would like to replace the start of the line/value. We replace this with ';' and save as our value. Then we output the object as you were already doing and then convert back to csv.
$path = 'F:\temp.csv'
Import-Csv $path | ForEach-Object {
$_ | Add-Member -NotePropertyName 'B' -NotePropertyValue ($_.A -replace '^', ';')
# or instead of -replace we can do similar to how you were trying
# $_ | Add-Member -NotePropertyName 'B' -NotePropertyValue (';' + $_.A)
$_
} | Export-Csv $path -NoTypeInformation
Update
Per your comment, this code should update values in all columns except the first where value is not null/empty
$path = 'F:\temp.csv'
$data = Import-Csv $path
# Track all the properties (columns) minus the first
$props = $data[0].psobject.Properties.Name | Select-Object -Skip 1
$data | ForEach-Object {
foreach ($prop in $props) {
if ( -not ([string]::IsNullOrWhiteSpace($_.$prop)) ){
$_.$prop = ';' + $_.$prop
}
}
$_
} | Export-Csv $path -NoTypeInformation

Make column and insert array contents inside the column.

I am reading in CSV file, after that I use -match to find a pattern I am looking for. I now have all of my matches inside a variable called $results. Next, I would like to create a new column and insert the contents of $results into that column. I have been stuck on this for a while, I have attempted to use for loops, forEach loops, if statements, and I cannot seem to get the results that I am looking for. I am new to Powershell, so I may be missing something obvious. Any help is greatly appreciated!
Here is my code:
$target = "This is the path to the .CSV file"
$pattern = '(V-\d*)'
$TestFile = (Get-Content $target)
$results = $TestFile | Select-String $pattern -AllMatches
$results.Matches.Value
#$TestFile -replace '(V-\d*)',' '
$NewFile = ConvertFrom-Csv $TestFile| Select-Object *,#{Name='Generic
Header';Expression={"Unsure of how to input data here without having all
data in same row"}}|export-csv ' Path for Exporting New .CSV file' -notype
Sample csv file with pattern in varying columns before
> import-csv .\SO_54012419.csv
col1 col2 col3
---- ---- ----
foo bar V-123
V-345 foo bar
bar V-789 foo
running this script:
$target = ".\SO_54012419.CSV"
$pattern = '(V-\d*)'
$csvdata = Import-Csv $target | Select-Object *,Result
foreach($row in $csvdata){
if ($row -match $pattern){
$Row.Result = $Matches[1]
}
}
$csvdata
$csvdata | Export-Csv 'Path for Exporting New.CSV' -NoTypeInformation
and after:
col1 col2 col3 Result
---- ---- ---- ------
foo bar V-123 V-123
V-345 foo bar V-345
bar V-789 foo V-789
If I understand the question correctly, I think this should do it:
$target = "This is the path to the .CSV file"
$pattern = '(V-\d*)'
$column = 'The name of the column to perform the regex match on'
# Read the input file as array of PSCustomObjects
$content = Import-Csv $target
# Do a foreach loop on each of the objects in the $content array
# and perform the regex -match on it. Add a new property (column) to every
# object in the array with the result of your regex match.
# Add an empty string if no match was found.
foreach ($item in $content) {
if ($item.$column -match $pattern) {
$item | Add-Member -MemberType NoteProperty -Name 'Result' -Value $matches[1]
}
else {
$item | Add-Member -MemberType NoteProperty -Name 'Result' -Value ''
}
}
# now use Export-Csv to write the new file complete with the new 'Result' header
$content | Export-Csv 'Path for Exporting New .CSV file' -NoTypeInformation

If Else statement Powershell CSV with Output CSV

I am fairly new in powershell scripting and need help on the following output in a csv format. I am trying to select a column e.g. ACCOUNT.UPLOAD and make and if/else statement to output it in another csv file. May someone help please.
Output csv should look like below:
$results = Import-Csv 'C:\Users\test\Desktop\Test\customer.csv' |
Select-Object "ACCOUNT.UPLOAD"
ForEach ($row in $results)
{
If ($row.Type0 -ne 'CP000101', 'CP000102')
{
$row."ACCOUNT.UPLOAD" = "$($row.ACCOUNT.UPLOAD)"
Write-Host $row."ACCOUNT.UPLOAD"
}
}
$results | Export-Csv C:\Users\test\Desktop\Test\test.csv -NoTypeInformation
Thank you
This will get you what you need. Added comments to explain what I have done.
$results = Import-Csv "C:\Users\test\Desktop\Test\customer.csv" | Select-Object "ACCOUNT.UPLOAD"
# Created array to be able to add individual results from foreach
$TheCSV = #()
ForEach ($row in $results) {
# You can use a -ne in the right hand side, if done like this.
If (($row.'ACCOUNT.UPLOAD' -ne 'CP000101') -and $row.'ACCOUNT.UPLOAD' -ne 'CP000102') {
# Adds the ROW column to the entry and finds the index that it was in from $results.
# Did a +2 as it does not include the header and it starts at value 0. So to match it up with the actual excel row numbers, add 2.
$row | Add-Member -Name 'ROW' -type NoteProperty -Value "$([array]::IndexOf($results.'ACCOUNT.UPLOAD',$row.'ACCOUNT.UPLOAD')+2)"
$TheCSV += $row
}
}
$TheCSV | Export-Csv "C:\Users\test\Desktop\Test\test.csv" -NoTypeInformation
Do it PowerShell way:
param(
[Parameter(Position=0)]
$InputFile = 'D:\\Temp\\Data.csv',
[Parameter(Position=1)]
$OutputFile = 'D:\\Temp\\Output.csv'
)
Import-Csv $InputFile |
Select-Object "ACCOUNT.UPLOAD" |
%{
$lineno++
if ($_.'ACCOUNT.UPLOAD' -notin #('CP000101', 'CP000102')) {
$_ | Add-Member -Name 'ROW' -type NoteProperty -Value $lineno
$_ # Output to pipeline
}
} -Begin { $lineno = 1 } |
Export-Csv $OutputFile -NoTypeInformation
Using:
.\Script.ps1
.\Script.ps1 inputfilename.csv outputfilefname.csv

Reformat CSV file in PowerShell

I have a well-formed CSV file that I want to read, reformatting some values while doing so. For some reason the code below does not work ($csv variable ends up being empty):
$csv = Import-Csv "result.log" -Delimiter "|" | ForEach-Object {
$_.PSObject.Properties.Value | ForEach-Object {
if ($_ -like '*---*') { $_ = "" }
}
}
What am I doing wrong?
Your result is blank because you aren't returning anything to the pipeline (you are just changing the value of one or more properties but then not outputting them).
There might be a simpler solution but I think this achieves what you want:
$CSV = Import-Csv "result.log" -Delimiter "|" | Foreach-Object {
$Output = New-Object -TypeName PSObject
$_.PSObject.Properties | Foreach-Object {
If ($_.Value -like '*---*') { $_.Value = '' }
$Output | Add-Member -Name $_.Name -Value $_.Value -MemberType NoteProperty
}
$Output
}
This performs the following for each row of the CSV:
creates a new empty PowerShell object
loops through the properties of the CSV, blanking ones that include --- and then uses Add-Member to add those properties to our object
outputs the new object to the standard pipeline
The result of this goes to the $CSV variable which you then could output as CSV via Export-CSV (or you could skip putting it in the variable and use Export-CSV on the end of the outer ForEach-Object).

try to determine the max number of character in each column

I have written a script that tries to determine the max no. of character for each column. This is what I wrote:
$path = 'folder path'
$file = Get-ChildItem $path\*
$FileContent = foreach ($files in $file) {
$FileHeader = #( (Get-Content $files -First 1).Split($delimiter) )
$importcsv = #( Import-Csv $files -Delimiter "$delimiter" )
for ($i=0; $i -lt $FileHeader.Length; $i++) {
#select each column
$Column = #( $importcsv | select $FileHeader[$i] )
#find the max no. of character
$MaxChar = #(($Column[$i] |
Select -ExpandProperty $FileHeader[$i] |
Measure-Object -Maximum -Property Length).Maximum)
$output = New-Object PSObject
$output | Add-Member NoteProperty FullName ($files.FullName)
$output | Add-Member NoteProperty FileName ($files.Name)
$output | Add-Member NoteProperty Time (Get-Date -Format s)
$output | Add-Member NoteProperty FileHeader ($($FileHeader[$i]))
$output | Add-Member NoteProperty MaxCharacter ($($MaxChar[$i]))
Write-Output $output
}
}
The script above is just part of it, so $delimiter is already defined. And finally I will export the result as CSV.
The script runs without any error, but when I open the file it only gives me the first column/header the max no. of character, and the rest of column/header are missing.
The perfect result will be showing each column/header the max no. of character.
Is something wrong with my loop?
my boss is trying to create an automate process to finding all the information from the raw data and use those information to upload to the database, so part of the script that is missing is about determine the delimiter of the raw file, the $CleanHeader is clean version of $FileHeader (remove all special characters, turn capital letters to small letters), those cleanheaders will be use for headers in the table in the database. and he also want to know the maximum character in each column, so that info can use them in creating the size of the column in the table in the database (he knows this part can be done in sql), but he ask me whether it can be done in PowerShell or not.
This should work:
$ht = #{}
# import a CSV and iterate over its rows
Import-Csv $f.FullName -Delimiter "$delimiter" | ForEach-Object {
# iterate over the columns of each row
$_.PSObject.Properties | ForEach-Object {
# update the hashtable if the length of the current column value is greater
# than the value in the hashtable
if ($_.Value.Length -gt $ht[$_.Name]) {
$ht[$_.Name] = $_.Value.Length
}
}
}
# create an object for each key in the hashtable
$date = Get-Date -Format s
$ht.Keys | ForEach-Object {
New-Object -Type PSObject -Property #{
FullName = $f.FullName
Name = $f.Name
Time = $date
FileHeader = $_
MaxCharacter = $ht[$_]
}
}
FileHeader[$i] was returning the column name with quotes : "ColumnName" instead of ColumnName
To fix, just add a trim to the line where you pull the header :
$FileHeader = #( (Get-Content $files -First 1).Split($delimiter).trim('"') )