Enclose columns in CSV with ~ - powershell

I have a CSV file with delimiter as | , the values between the delimiter are not enclosed between quotes or any character. I am trying out a way to accept this file as an input and export a new CSV file with all the column to be enclosed in ^
Example:
Input:
1|Test|3
Output:
^1^|^Test^|^3^
Have tried below code but in vain:
get-content C:\ip.csv | foreach-object { $_ -replace '|' ,'^'} | set-content C:\op.csv

Try this:
$cont = get-content "D:\path\file.csv"
$cont | % {
$info = "^" + $_.Split("|")[0] + "^" + $_.Split("|")[1] + "^" + $_.Split("|")[2] + "^"
$info
}

Related

Change pipe delimited file to comma delimited in Powershell

I have a pipe delimited .TXT file. I need to change the delimiter to a comma instead but still keep the file extension as .TXT. The file looks like this:
Column 1 |Column 2
13|2019-09-30
96|2019-09-26
173|2019-09-25
I am using Windows Powershell 5.1 version for my script.
I am using the following code:
$file = New-Object System.IO.StreamReader -Arg "c:\file.txt"
$outstream = [System.IO.StreamWriter] "c:\out.txt"
while ($line = $file.ReadLine()) {
$s = $line -replace '|', ','
$outstream.WriteLine($s)
}
$file.close()
$outstream.close()
Instead of just replacing the pipe with a comma, the output file looks like this:
C,o,l,u,m,n, 1 , |,C,o,l,u,m,n, 2
1,3,|,2,0,1,9,-,0,9,-,3,0
9,6,|2,0,1,9,-,0,9,-,2,6
1,7,3,|,2,0,1,9,-,0,9,-,2,5
The only problem with your answer is in how you try to replace the | characters in the input:
$s = $line -replace '|', ',' # WRONG
PowerShell's -replace operator expects a regex (regular expression) as its first RHS operand, and | is a regex metacharacter (has special meaning)[1]; to use it as a literal character, you must \-escape it:
# '\'-escape regex metacharacter '|' to treat it literally.
$s = $line -replace '\|', ','
While PowerShell's -replace operator is very flexible, in simple cases such as this one you can alternatively use the [string] type's .Replace() method, which performs literal string replacements and therefore doesn't require escaping (it's also faster than -replace):
# Use literal string replacement.
# Note: .Replace() is case-*sensitive*, unlike -replace
$s = $line.Replace('|', ',')
[1] | denotes an alternation in a regex, meaning that the subexpressions on either side are matched against the input string and one of them matching is sufficient; if your full regex is just |, it effectively matches the empty string before and after each character in the input, which explains your symptom; e.g., 'foo' -replace '|', '#' yields #f#o#o#
You can use Import-Csv and Export-Csv by specifying the -Delimiter.
Import-Csv -Delimiter '|' -Path "c:\file.txt" | Export-Csv -Delimiter ',' -Path "c:\file.txt" -NoTypeInformation
You will find the -split and -join operators to be of interest.
Get-Content -Path "C:\File.TXT" | ForEach-Object { ($_ -split "\|") -join "," } | Set-Content -Path "C:\Out.TXT"

How do I add multi-line strings to an array in powershell?

I'm trying to loop through a series of txt files extracting information into arrays based a : delimiter.
All values i'm taking from the text files fit on a single line, except for one. (The "ad text" value). This cuts off the information after line 1 in the final output. When I remove line carriages and breaks beforehand, none of the fields are inputted correctly.
How would I specify wanting my array to accept multi-line inputs for the "ad text" field?
Below is the code i'm working with:
$files = ls "*.txt"
$dictionary = #{}
[System.Collections.Generic.List[String]]$list = #()
foreach($f in $files){$in = Get-Content $f
$in.Split([Environment]::NewLine) | ForEach-Object { $key,$value = $_.Split(':')
$dictionary[$key] = $value
}
[void]$list.Add( $dictionary['Ad ID'] + ',' + $dictionary['Ad Text'] + ',' + $dictionary['Ad Landing Page'] + ',' + $dictionary['Ad Targeting Location'] + ',' + $dictionary['Age'] + ',' + $dictionary['Language'] + ',' + $dictionary['Placements'] + ',' + $dictionary['Interests'] + ',' + $dictionary['Behaviors'] + ',' + $dictionary['Ad Impressions'] + ',' + $dictionary['Ad Clicks'] + ',' + $dictionary['Ad Spend'] + ',' + $dictionary['Ad Creation Date'] + ','+ $dictionary['Friends'] + ',' + $dictionary['Ad End Date'] + ',' + $dictionary['Excluded Connections'] + ',' + $dictionary['Image'] + ',' + $dictionary['Ad Targeting Location']+','+$dictionary[‘File Name’] )
}
$list | Out-File -FilePath '.\trial.csv' -Append
Assuming that the additional lines following Ad Text:-prefixed lines do not contain : chars themselves:
# Create sample text file t.txt
#'
Ad ID:10
Ad Text:one
two
Ad Landing Page:http://example.org
'# > t.txt
# Split the lines into field names and values by ":" and
# build a dictionary.
$dict = [ordered] #{}
$i = 0
(Get-Content -Raw t.txt) -split '(?m)^([^\n:]+):' -ne '' | ForEach-Object {
if ($i++ % 2 -eq 0) {
$key = $_
} else {
$dict[$key] = $_
}
}
# Output the dictionary, showing each entry as a list.
$dict | Format-List
The output is as follows, showing that the Ad Text entry comprises two lines:
Name : Ad ID
Value : 10
Name : Ad Landing Page
Value : http://example.org
Name : Ad Text
Value : one
two

Sort and export-CSV

I have a csv file containing rows of the following extract:
"EmployeeID","FirstName","LastName","Location","Department","TelephoneNo","Email"
"000001 ","abc ","def ","Loc1"," "," ","name1#company.com "
"000023 ","ghi ","jkl ","Loc2"," "," ","name2#company.com "
"000089 ","mno ","pqr ","Loc2"," "," ","name3#company.com "
How do I keep the quotes and sort and save as a csv file?
I have the following powershell source script which works with csv files not having double quotes for the columns:
Get-Content $Source -ReadCount 1000 |
ConvertFrom-Csv -Delimiter $Delimiter |
Sort-Object -Property $NamesOfColumns -Unique |
ForEach-Object {
# Each of the values in $ColumnValueFormat must be executed to get the property from the loop variable ($_).
$values = foreach ($value in $ColumnValueFormat) {
Invoke-Expression $value
}
# Then the values can be passed in as an argument for the format operator.
$ShowColsByNumber -f $values
} |
Add-Content $Destination;
The $Source, $Delimiter, $NamesOfColumns and $ColumnValueFormat are given or built dynamically.
$ColumnValueFormat with a non quoted csv file contains:
$_.EmployeeID.Trim()
$_.FirstName.Trim()
$_.LastName.Trim()
$_.Location.Trim()
$_.Department.Trim()
$_.TelephoneNo.Trim()
$_.Email.Trim()
$ColumnValueFormat with a quoted csv file contains:
$_."EmployeeID".Trim()
$_."FirstName".Trim()
$_."LastName".Trim()
$_."Location".Trim()
$_."Department".Trim()
$_."TelephoneNo".Trim()
$_."Email".Trim()
The problem seems to be based around the $ColumnValueFormat that is placing the column headers with the double quotes. (If I remove them I am not sure the internals of the cmdlet will recognize the column headings when it is processing the rows)
I am having two problems:
The column heading surrounded by the double quotes. The problem seems to be based around the $ColumnValueFormat that is placing the column headers with the double quotes as it does not process the rows. (If I remove the double quotes then it does not recognize the column headings when it is processing the rows).
Another problem I came across last minute is if the last column is blank it thinks it's a null and when the Invoke-Expression $value executes (where $value holds the last column expression of $_.Email.Trim() - on a non quoted CSV file) it bombs. If I try to place the statement in a try/catch block it simply ignore it the last column is not added to the $values array and again bombs.
Quotes around property names are used syntactically to access names with spaces, not to write quotes to the output.
Export-Csv cmdlet doesn't have an option to force quotes so we'll have to export the CSV manually. And we'll have to process empty values that are $Null after ConvertFrom-Csv with an empty string. In case only some fields are needed we'll use Select cmdlet with -index parameter.
Get-Content $Source |
ConvertFrom-Csv |
%{ $header = $false } {
if (!$header) {
$header = $true
'"' + (
($csv[0].PSObject.Properties.Name.trim() |
select -index 1,6
) -join '","'
) + '"'
}
'"' + (
($_.PSObject.Properties.Value |
%{ if ($_) { $_.trim() } else { '' } } |
select -index 1,6
) -join '","'
) + '"'
} | Out-File $Destination
The above code is great for pass-through processing of large CSV files because it doesn't keep the entire file in memory. Otherwise it's possible to simplify the code a bit:
$csv = Get-Content $Source | ConvertFrom-Csv
$csv | %{
'"' + (
($csv[0].PSObject.Properties.Name.trim() |
select -index 1,6
) -join '","'
) + '"'
} {
'"' + (
($_.PSObject.Properties.Value |
%{ if ($_) { $_.trim() } else { '' } } |
select -index 1,6
) -join '","'
) + '"'
) | Out-File $Destination

Remove character from file name in powershell

I'm new to powershell and wanted to know if there's a way to remove a character from a file name. The character I'm trying to remove is a dash "-" and sometimes there are 2 or 3 dashes in the file name. Is it possible to have it rename files that have a dash in them?
Get-Item .\some-file-with-hyphens.txt | ForEach-Object {
Rename-Item $_ ($_.Name -replace "-", "")
}
This question may be more suitable for SuperUser.
To remove or replace characters in a file name use single quotes ' and for "special" characters escape them with a backslash \ so the regular expression parser takes it literally.
The following removes the $ (dollar sign) from all file names in your current directory:
Get-Item * | ForEach-Object { rename-item $_ ($_.Name -replace '\$', '') }
the following is the same as above using the shorter alias for each command:
gi * | % { rni $_ ($_.Name -replace '\$', '') }
The following is removing the standard character "Z" from all file names in your current directory:
gi * | % { rni $_ ($_.Name -replace 'Z', '') }

Problems with replacing newline

Iam trying to replace following string with PowerShell:
...
("
Intel(R) Network Connections 14.2.100.0
","
14.2.100.0
")
...
The code that I use is:
Get-Content $logfilepath |
Foreach-Object { $_ -replace '`r`n`r`n', 'xx'} |
Set-Content $logfilepath_new
But I have no success, can someone say me, where the error is?
First, you are using single quotes in the replace string -
'`r`n`r`n'
that means they are treated verbatim and not as newline characters, so you have to use -
"`r`n`r`n"
To replace, read the file as string and use the Replace() method
$content=[string] $template= [System.IO.File]::ReadAllText("test.txt")
$content.Replace("`r`n`r`n","xx")
Get-content returns an array of lines, so CRLF is essentially your delimiter. Two CRLF sequences back to back would be interpreted as the end of the currrent line, followed by a null line, so no line (object) should contain '`r`n`r`n'. A multi-line regex replace would probably be a better choice.
as alternate method using PS cmdlets:
Get-Content $logfilepath |
Foreach-Object -Begin { $content="" } -Process { $content += $_ ; $content += "xx" } -End { $content } |
Set-Content $logfilepath_new
I used the following code to replace somestring with newline:
$nl = [System.Environment]::NewLine
$content = $content.Replace( somestring, $nl )