Как удалить все кавычки в файле csv с помощью сценария PowerShell?
Я хотел бы удалить все символы цитат в моем экспортированном файле csv, это очень раздражает, когда я сгенерировал новый файл csv, и мне нужно вручную удалить все цитаты, включенные в строку. Может ли кто-нибудь предоставить мне сценарий Powershell для решения этой проблемы? Спасибо.
$File = "c:\programfiles\programx\file.csv"
(Get-Content $File) | Foreach-Object {
$_ -replace """, ""
} | Set-Content $File
8 ответов
В следующий раз, когда вы сделаете его, в export-csv в PowerShell 7 появится новая опция, которая может вам понравиться:
export-csv -UseQuotes AsNeeded
Кажется, многие из нас уже объяснили, что в файлах CSV иногда нужны кавычки. Это тот случай, когда:
- значение содержит двойную кавычку
- значение содержит символ-разделитель
- значение содержит символы новой строки или пробелы в начале или в конце строки
В PS версии 7 у вас есть возможность использовать параметр -UseQuotes AsNeeded
. Для более старых версий я сделал эту вспомогательную функцию для преобразования в CSV, используя при необходимости только кавычки:
function ConvertTo-CsvNoQuotes {
# returns a csv delimited string array with values unquoted unless needed
[OutputType('System.Object[]')]
[CmdletBinding(DefaultParameterSetName = 'ByDelimiter')]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
[PSObject]$InputObject,
[Parameter(Position = 1, ParameterSetName = 'ByDelimiter')]
[char]$Delimiter = ',',
[Parameter(ParameterSetName = 'ByCulture')]
[switch]$UseCulture,
[switch]$NoHeaders,
[switch]$IncludeTypeInformation # by default, this function does NOT include type information
)
begin {
if ($UseCulture) { $Delimiter = (Get-Culture).TextInfo.ListSeparator }
# regex to test if a string contains a double quote, the delimiter character,
# newlines or has whitespace at the beginning or the end of the string.
# if that is the case, the value needs to be quoted.
$needQuotes = '^\s|["{0}\r\n]|\s$' -f [regex]::Escape($Delimiter)
# a boolean to check if we have output the headers or not from the object(s)
# and another to check if we have output type information or not
$doneHeaders = $doneTypeInfo = $false
}
process {
foreach($item in $InputObject) {
if (!$doneTypeInfo -and $IncludeTypeInformation) {
'#TYPE {0}' -f $item.GetType().FullName
$doneTypeInfo = $true
}
if (!$doneHeaders -and !$NoHeaders) {
$row = $item.PsObject.Properties | ForEach-Object {
# if needed, wrap the value in quotes and double any quotes inside
if ($_.Name -match $needQuotes) { '"{0}"' -f ($_.Name -replace '"', '""') } else { $_.Name }
}
$row -join $Delimiter
$doneHeaders = $true
}
$item | ForEach-Object {
$row = $_.PsObject.Properties | ForEach-Object {
# if needed, wrap the value in quotes and double any quotes inside
if ($_.Value -match $needQuotes) { '"{0}"' -f ($_.Value -replace '"', '""') } else { $_.Value }
}
$row -join $Delimiter
}
}
}
}
Используя ваш пример для удаления ненужных кавычек в существующем файле CSV:
$File = "c:\programfiles\programx\file.csv"
(Import-Csv $File) | ConvertTo-CsvNoQuotes | Set-Content $File
Помня , что это может привести к повреждению ваших данных, если вы встроили в них двойные кавычки, вот еще один вариант идеи... [усмехается]
что оно делает...
- определяет входные и выходные полные имена файлов
- хватает
*.tmp
файлы из временного каталога - фильтры для первых трех файлов и только трех основных свойств
- создает файл для работы с
- загружает содержимое файла
- заменяет двойные кавычки ничем
- сохраняет очищенный файл под второе имя файла
- отображает исходную и очищенную версии файла
код...
$TestCSV = "$env:TEMP\Ted.Xiong_-_Test.csv"
$CleanedTestCSV = $TestCSV -replace 'Test', 'CleanedTest'
Get-ChildItem -LiteralPath $env:TEMP -Filter '*.tmp' -File |
Select-Object -Property Name, LastWriteTime, Length -First 3 |
Export-Csv -LiteralPath $TestCSV -NoTypeInformation
(Get-Content -LiteralPath $TestCSV) -replace '"', '' |
Set-Content -LiteralPath $CleanedTestCSV
Get-Content -LiteralPath $TestCSV
'=' * 30
Get-Content -LiteralPath $CleanedTestCSV
выход...
"Name","LastWriteTime","Length"
"hd4130E.tmp","2020-03-13 5:23:06 PM","0"
"hd418D4.tmp","2020-03-12 11:47:59 PM","0"
"hd41F7D.tmp","2020-03-13 5:23:09 PM","0"
==============================
Name,LastWriteTime,Length
hd4130E.tmp,2020-03-13 5:23:06 PM,0
hd418D4.tmp,2020-03-12 11:47:59 PM,0
hd41F7D.tmp,2020-03-13 5:23:09 PM,0
Одно из решений не удалять двойные кавычки в цитируемой строке:
$delimiter=","
$InputFile="c:\programfiles\programx\file.csv"
$OutputFile="c:\programfiles\programx\resultfile.csv"
#import file in variable (not necessary if your faile is big repeat this import where i use $ContentFile)
$ContentFile=import-csv $InputFile -Delimiter $delimiter -Encoding utf8
#list of property of csv file
$properties=($ContentFile | select -First 1 | Get-Member -MemberType NoteProperty).Name
#write header into new file
$properties -join $delimiter | Out-File $OutputFile -Encoding utf8
#write data into new file
$ContentFile | %{
$RowObject=$_ #==> get row object
$Line=@() #==> create array
$properties | %{$Line+=$RowObject."$_"} #==> Loop on every property, take value (without quote) inot row object
$Line -join $delimiter #==> join array for get line with delimer and send to standard outut
} | Out-File $OutputFile -Encoding utf8 -Append #==> export result to output file
Как и выше, цитаты действительны для csv, но для их удаления вам нужно экранировать кавычки в операции замены, так как это специальный символ:
$File = "c:\programfiles\programx\file.csv"
(Get-Content $File) | Foreach-Object {
$_ -replace "`"", ""
} | Set-Content $File
После того, как вы экспортировали файл CSV с Export-CSV
, вы можете использовать Get-Content
чтобы загрузить файл CSV в массив строк, затем используйте Set-Content
а также replace
убрать кавычки:
Set-Content -Path sample.csv -Value ((Get-Content -Path sample.csv) -replace '"')
Как услужливо указал mklement0, это может потенциально повредить CSV, если некоторые строки нуждаются в цитировании. Это решение просто просматривает весь файл и заменяет каждую цитату на''
.
Вы также можете ускорить это с помощью -Raw
переключиться с Get-Content
, который возвращает целую строку с сохраненными символами новой строки вместо массива строк с разделителями новой строки:
Set-Content -NoNewline -Path sample.csv -Value ((Get-Content -Raw -Path sample.csv) -replace '"')
Чтобы избежать двойных кавычек в строке, можно использовать дополнительные двойные кавычки:
$File = "c:\programfiles\programx\file.csv"
(Get-Content $File) | Foreach-Object { $_ -replace """", "" } | Set-Content $File
Почему вы вручную в текстовом редакторе читаете файлы CSV?
Вы не зря экспортировали их в этот формат. Чтобы прочитать их, просто импортируйте их обратно и просмотрите их на экране или прочтите их обратно и отправьте результат в блокнот для чтения.
Export-Csv -Path D:\temp\book1.csv
Import-Csv -Path D:\temp\book1.csv |
Clip |
Notepad # then press crtl+v, then save the notepad file with a new name.
Если вам не нужен Csv, не экспортируйте как Csv, просто выводите как плоский файл, используя вместо этого Out-File.
Обновить
Поскольку ваш последний комментарий ко мне указал на ваш последний вариант использования. CSV в SQL - очень распространенная вещь. Быстрый поиск в Интернете покажет вам, как даже предоставить вам сценарий.Вам также следует обратить внимание на модуль PowerShell DBATools.
Как импортировать данные из.csv в SQL Server с помощью PowerShell?
Импорт файлов CSV в базу данных Microsoft SQL с помощью PowerShell
Четыре простых способа импорта файлов CSV в SQL Server с помощью PowerShell
Find-Module -Name '*dba*'
<#
Version Name Repository Description
------- ---- ---------- -----------
1.0.101 dbatools PSGallery The community module that enables SQL Server Pros to automate database development and server administration
...
#>
Обновить
Вы имеете в виду это...
Get-Content 'D:\temp\book1.csv'
<#
# Results
"Site","Dept"
"Main","aaa,bbb,ccc"
"Branch1","ddd,eee,fff"
"Branch2","ggg,hhh,iii"
#>
Get-ChildItem -Path 'D:\temp' -Filter 'book1.csv' |
ForEach {
$NewFile = New-Item -Path 'D:\Temp' -Name "$($PSItem.BaseName).txt"
Get-Content -Path $PSItem.FullName |
ForEach-Object {
Add-Content -Path $NewFile -Value ($PSItem -replace '"') -WhatIf
}
}
<#
What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt"
#>
Get-ChildItem -Path 'D:\temp' -Filter 'book1.csv' |
ForEach {
$NewFile = New-Item -Path 'D:\Temp' -Name "$($PSItem.BaseName).txt"
Get-Content -Path $PSItem.FullName |
ForEach-Object {
Add-Content -Path $NewFile -Value ($PSItem -replace '"')
}
}
Get-Content 'D:\temp\book1.txt'
<#
# Results
Site,Dept
Main,aaa,bbb,ccc
Branch1,ddd,eee,fff
Branch2,ggg,hhh,iii
#>
Конечно, вам нужно использовать подстановочный знак для файлов csv и использовать -Resurse для получения всех каталогов и обработчика ошибок, чтобы убедиться, что у вас нет конфликтов имен файлов.