replace a string in a csv file with powershell - powershell

I need to place System.Object[] for some columns in a csv file. I tried 3 different method but none of them are working. System.Object[] is put in by powershell when that object is empty or something.
$file = "c:\output.csv"
(gc $file) -replace "'system.object[]'", ""
[io.file]::readalltext($file).replace("'system.object[]'","")
(Get-Content $file | ForEach-Object { $_ -replace "system.object[]", "" } ) | Set-Content $file

I added following code to the variable that containing System.Object[] on output. and it's seems to be working. and now I dont have to do the replacement at file level.
"Access Code" = (#($AccessCode) | Out-String).Trim()

The bracers and the dot ([, ], .) need all to be escaped. Furthermore remove the double quotation marks, just keep the single ones. Also think about using creplace, in case you want to work case insensitive. So the command would look like this:
(gc $file) -replace 'system\.object\[\]', ''
In case you want to write everything to a new file:
(gc $file) -replace 'system\.object\[\]', ''|out-file "test2.txt" -encoding ASCII

Just use Escape character
(gc $file) -replace 'system.object\[\]', ""
The characters '[' and ']' are used for Regex pattern. You must use Escape
character '\' to tell Powershell that This is a regular chars

Related

Select-String successfully finds a string, replacing that found string with something else fails

uniquefile1.txt is a file that has no carriage returns (if it matters) and is very long. I am trying to match a variety of patterns.
The text file is not open when the program runs.
I visually have checked that the file has my pattern exactly as
written, when using Select-String it confirms that the pattern
exists.
When I go to replace, if I do Out-Host and search my
output in my ide it does not show that it has changed. It is not
replacing this string, and I do not know what I am doing wrong.
There are no errors of any kind when running my code.
I have tried:
$file = Get-Content C:\Uniqueline1
$file.Replace($variableforpattern1, $varForReplacement) | Set-Content Uniquefile1.txt
As well as the above except with the actual strings in place of the variables.
$file = Get-Content C:\uniquefile1.txt -Raw
$SEL = Select-String -Path "C:\uniquefile1.txt" -Pattern ">>>11^A"
if ($SEL = $true)
{
write "true"
}
else
{
write "not true"
}
$file -replace ">>>11^A", ">>>0111^A" | Set-Content "C:\uniquefile1.txt"
AdminOfThings was correct, please see their comment. This character ^ has special meaning in Regex and must be escaped.
-replace uses regex for the search pattern and therefore must have regex-special characters escaped if they are to be matched literally. The \ is used for escaping.
$file = Get-Content C:\uniquefile1.txt -Raw
$file -replace '>>>11\^A', '>>>0111^A' | Set-Content C:\uniquefile1.txt
Select-String without the -SimpleMatch switch uses regex as well. I don't know how that ever matched for you if the -replace operation failed.

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"

Replace ^M with <space> in all lines of a file

I have a log file with ^M embedded throughout. I would like to replace the ^M with a single space.
I have tried variations on this:
(Get-Content C:\temp\send.log) | Foreach-Object {$_ -replace "^M", ' '} | Set-Content C:\temp\send.out
The output file contains a newline where each ^M had been, not at all what I was looking for...
The problem I am trying to solve involves examining the last $cnt lines of the file:
$new = Get-Content $fn | Select-Object -Last $cnt;
$new
When I display $new, the ^M are interpreted as CR/LF.
How can I remove/replace the ^M? Thanks for any pointers....
Sounds like ^M is not being replaced by your -replace method, it's likely the replace method is trying to replace capital letter M at the beginning of the string (^). Upon opening the file, ^M is then being interpreted as a carriage return.
Perhaps try replacing the carriage returns (^M) before displaying the contents:
(Get-Content C:\temp\send.log) |
Foreach-Object {$_ -replace "`r", ' '} |
Set-Content C:\temp\send.out
or
$new = Get-Content $fn | Select-Object -Last $cnt;
$new.replace("`r"," ")
Could this be as simple as escaping the ^ character? If you only need the last $count lines of the file you can use the -Tail parameter on Get-Content. Depending if you need to match ^M as case sensitive you might opt for -creplace instead of -replace.
Get-Content $inputfile -Tail $count | ForEach-Object { $_ -creplace '\^m',' ' } | Set-Content $outputfile
This isn't an answer, but since you asked for a few pointers, this might help set things straight.
Try this:
$new = Get-Content $fn | Select-Object -Last $cnt;
$new
$new.gettype()
$new[0].gettype()
I expect you're going to see that $new is an array of objects, and that $new[0] is a string. I'm going to suggest that $new[0] doesn't contain CR or LF or CRLF or anything like that. And I'm going to suggest that, when you ask for the display of $new in its entirety, what you are getting is each string ($new[0] followed by $new[1] ...) with CRLF inserted as a separator.
If I'm right, replacing CR or CRLF with space isn't going to do you any good at all. It's the CRLFs that are being inserted on output to a file that are preventing you from succeeding.
This is as far as I got towards solving your problem.

In Powershell Script, how do I convert a pipe '|' delimited file to a comma ',' delimited CSV?

In Powershell Script, how do I convert a | (pipe) delimited CSV file to a , (comma) delimited CSV file?
When we use the following command in Windows Powershell Encoding 'UTF8' -NoType to convert from | (pipe delimiter) to , (comma delimiter), the file is converted with , delimited but the string was surrounded by " " (double quotes). Like given below:
Source file data:
ABC|1234|CDE|567|
Converted file data:
"ABC","1234","CDE","567",
I want to generate the following:
ABC,1234,CDE,567,
What command can I use to convert the delimiter from | to ,?
I would use:
(Get-Content -Path $file).Replace('|',',') | Set-Content -Path $file
You must escape the pipe, so:
(get-content "d:\makej\test.txt" ) -replace "\|","," | set-content "d:\makej\test.csv"
Seems easy enough:
(get-content $file) -replace '|',',' | set-content $file
In general, you should use the commands Import-Csv and Export-Csv which properly handle delimiters embedded in the field values, such as Field,1|Field2. The Get-Content based solutions would turn this into 3(!) fields Field,1,Field2, while the output actually should be quoted like "Field,1",Field2 or "Field,1","Field2".
Import-Csv input.csv -Delimiter '|' | Export-Csv output.csv -Delimiter ','
This always quotes fields in "output.csv". Since PowerShell (Core) 7+, the new Export-Csv parameters -UseQuotes and -QuoteFields allow us to control the quoting of the output file.
E. g. to quote only if necessary (when a field value contains the delimiter or quotation marks):
Import-Csv input.csv -Delimiter '|' | Export-Csv output.csv -Delimiter ',' -UseQuotes AsNeeded
Be careful with -UseQuotes Never, because it can render the output file unreadable, if a field value contains embedded delimiter or quotation marks.
Here is a function to convert to unquoted CSV for PowerShell 5.x (possibly supports older versions as well). This is like -UseQuotes Never, so make sure your data doesn't contain the delimiter. Additionally you may omit the header by passing the -NoHeader switch.
Function ConvertTo-CsvUnquoted {
[CmdletBinding()]
param (
[Parameter(Mandatory, ValueFromPipeline)] $InputObject,
[string] $Delimiter = ',',
[switch] $NoHeader
)
process {
if( -not $NoHeader ) {
$_.PSObject.Properties.Name -join $Delimiter
$NoHeader = $true
}
$_.PSObject.Properties.Value -join $Delimiter
}
}
Usage example:
Import-Csv input.csv | ConvertTo-CsvUnquoted -Delimiter '|' | Set-Content output.csv
Sorry this may need some tweaking on your part, but it does the job. Note that this also changes the file type from .txt to .csv which I dont think you wanted.
$path = "<Path>"
$outPath = $path -replace ".txt",".csv"
Get-Content -path $path |
ForEach-Object {$_ -replace "|","," } |
Out-File -filepath $outPath
I view the suggested answers as a little risky, because you are getting the entire contents of the existing file into memory, and therefore won't scale well, and risks using a lot of memory. My suggestion would be to use the string replace as the previous posts suggested, but to use streams instead for both reading and writing. That way you only need memory for each line in the file rather than the entire thing.
Have a look here at one of my other answers here:
https://stackoverflow.com/a/32337282/380016
And in my sample code you'd just change the string replace to:
$s = $line -replace '|', ','
And also adjust your input and output filenames accordingly.

PowerShell script to convert one-column CSV file

I'm looking for a script, doesn't have to be in PS but must run under Windows, that converts a one column text file like below
abc
def
ghi
into
'abc',
'def',
'ghi'
I'm currently making this change in Excel using =concatenate, but a script would be better.
Use can use a regular expression to insert characters at beginning and end.
get-content ./myonlinecolumn.txt | foreach {$_ -replace "^","'" -replace "`$","',"}
Or you could use the format operator -f:
get-content ./myonlinecolumn.txt | foreach {"'{0}'," -f $_ }
Its a bit more work to remove the last trailing comma, but this also possible
$a = get-content ./myonlinecolumn.txt
get-content ./myonlinecolumn.txt | foreach { if ($_.readcount -lt $a.count) {"'{0}'," -f $_ } else {"'{0}'" -f $_ }}
My first idea was similar to what Chad already wrote, that is a check on the line number. So I've tried a different solution. Not very nice but I post it too :)
((gc c:\before.txt | % {"'"+$_+"'"} ) -join ",*").split("*") | out-file c:\after.txt
You can just use
(gc myfile | %{"'$_'"}) -join ',
'
or, if you love escapes:
(gc myfile | %{"'$_'"}) -join ",`n"
This loads the file into an array of strings (Get-Content), then processes each string by putting it into single quotes. (Use `"'$($_.Trim())'" if you need to trim whitespace, too). Then the lines are joined with a comma and line break (those can be embedded directly into strings).
If your values can contain single quotes (which need to be escaped) it's trivial to stick that in there, too:
(gc myfile | %{"'$($_.Trim() -replace "'","''")'"}) -join ",`n"