Хотя я думаю, что это создаст файл CSV странного формата, с PowerShell вы можете использовать switch
вместе с параметрами -Regex
и -File
. Вероятно, это самый быстрый способ обработки больших файлов, и он занимает всего несколько строк кода:
# create a regex that will find comma's unless they are inside single quotes
$commaUnlessQuoted = ",(?=([^']*'[^']*')*[^']*$)"
$result = switch -Regex -File 'D:\test.csv' {
# added -replace "'" to also remove the single quotes as commented
default { $_ -replace "$commaUnlessQuoted", '|*' -replace "'" }
}
# output to console
$result
# output to new (sort-of) CSV file
$result | Set-Content -Path 'D:\testoutput.csv'
Обновление As mklement0 указал приведенный выше код делает работу, но за счет создания обновленных данных в виде массива в памяти полностью до записи в выходной файл.
Если это проблема (файл тоже большой, чтобы вместить доступную память), вы также можете изменить код для чтения / замены строки из оригинала и сразу записать эту строку в выходной файл.
Этот следующий подход вряд ли будет использовать какую-либо память, но, конечно, за счет выполнения гораздо большего количества действий записи на диск ..
# make sure this is an absolute path for .NET
$outputFile = 'D:\output.csv'
$inputFile = 'D:\input.csv'
# create a regex that will find comma's unless they are inside single quotes
$commaUnlessQuoted = ",(?=([^']*'[^']*')*[^']*$)"
# create a StreamWriter object. Uses UTF8Encoding without BOM (Byte Order Mark) by default.
# if you need a different encoding for the output file, use for instance
# $writer = [System.IO.StreamWriter]::new($outputFile, $false, [System.Text.Encoding]::Unicode)
$writer = [System.IO.StreamWriter]::new($outputFile)
switch -Regex -File $inputFile {
default {
# added -replace "'" to also remove the single quotes as commented
$line = $_ -replace "$commaUnlessQuoted", '|*' -replace "'"
$writer.WriteLine($line)
# if you want, uncomment the next line to show on console
# $line
}
}
# remove the StreamWriter object from memory when done
$writer.Dispose()
Результат:
123|*abc,def,ghf|*ajajaj|*1
345|*abdf|*abc,def,ghi|*2
556|*abdf|*def|*3
999|*a,b,d|*d,e,f|*4
Regex детали:
, Match the character “,” literally
(?= Assert that the regex below can be matched, starting at this position (positive lookahead)
( Match the regular expression below and capture its match into backreference number 1
[^'] Match any character that is NOT a “'”
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
' Match the character “'” literally
[^'] Match any character that is NOT a “'”
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
' Match the character “'” literally
)* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
[^'] Match any character that is NOT a “'”
* Between zero and unlimited times, as many times as possible, giving back as needed (greedy)
$ Assert position at the end of the string (or before the line break at the end of the string, if any)
)