PowerShell Import-CSV в Export-CSV с преобразованием типов
Я получаю кучу файлов с разделителями табуляции и хочу преобразовать их в файлы с разделителями-запятыми. Мне также нужны только два столбца из файла "Дата" и "Значение1", поэтому я отбрасываю остальные столбцы.
Date Value1 Value2 Value3 Value4 Sensor
08.07.2010 115,28 115,45 115,45 115,28 100
07.07.2010 115,34 115,32 115,34 115,25 85
06.07.2010 115,23 115,74 115,74 115,20 203
Это работает следующим образом:
(get-ChildItem -Path '*.txt').name | ForEach-Object {
Import-Csv -Path $_ -Delimiter "`t" |
Select-Object -Property Date,Value1 |
Export-Csv "out\$_"
}
К сожалению, в исходном файле запятая используется в качестве десятичного разделителя. Таким образом, я получаю эти файлы, где Value1 интерпретируется как строка:
"Date","Value1"
"24.02.2017","30,18"
"23.02.2017","30,20"
"22.02.2017","30,18"
"21.02.2017","30,18"
"20.02.2017","30,17"
Как я могу установить тип данных столбца числовой? В течение Import-CSV
?
2 ответа
Export-CSV
всегда добавляя "..."
вокруг значений выходного поля нет (само по себе) проблемы:
Формат данных CSV не имеет внутренней концепции типа данных, и двойные кавычки используются исключительно для включения значения поля (что является синтаксическим требованием для значений поля со встроенным
,
chars., например).Например, Excel выводит тип данных столбца исключительно из его содержимого, независимо от того, заключено ли это содержимое в двойные кавычки или нет.
- Интерпретация контента, однако, учитывает культуру (локаль).
В отличие от PowerShell
Import-Csv
никогда не интерпретирует данные и возвращает все значения полей как строки.
В зависимости от активной культуры в среде, в которой будет обрабатываться CSV, у вас есть два варианта:
Для такой культуры, как
de-DE
(Германия), в которой,
(запятая), а не.
(точка, точка) используется в качестве десятичного знака, и;
скорее, чем,
используется в качестве разделителя списка:- При действующей целевой культуре (проверьте с помощью
Get-Culture
) использоватьExport-Csv -UseCulture
(-UseCulture
доступно начиная с (как минимум) v2 [1]). Спасибо, LotPings - В качестве альтернативы используйте что-то вроде
Export-Csv -Delimiter ([cultureinfo]::GetCultureInfo('de-DE').TextInfo.ListSeparator)
- При действующей целевой культуре (проверьте с помощью
Для англоязычной культуры (или любой другой культуры, которая использует
.
как десятичная дробь):- Произведите пользовательскую обработку файла и замените
,
экземпляры в числовых полях с.
- увидеть ниже.
- Произведите пользовательскую обработку файла и замените
Чтобы заменить ,
случаи с .
, следующая команда, которая использует только строковые манипуляции, сделает:
Get-ChildItem -Path *.txt | ForEach-Object {
Get-Content -LiteralPath $_.FullName | ForEach-Object {
($_ -split '\t')[0,1] -replace ',', '.' -join ','
} |
Set-Content -Encoding utf8 "out/$($_.Name)"
}
Примечание. Для простоты команда предполагает, что Date
значения столбца не содержат экземпляров ,
и что ни одно из значений не требует "..."
- Включение - что является разумным в этом конкретном сценарии.
- Я выбрал UTF-8 в качестве выходной кодировки выше, потому что
Set-Content
по умолчанию используется устаревшая, специфичная для культуры кодовая страница "ANSI" - при необходимости измените.
[1] Как правило, если в описании параметра в разделе справки по командлету не упоминается конкретная версия, в которой он был представлен, это означает, что он существует со времен v2. Теперь вы можете просматривать более старые версии документации - вплоть до версии 3 - на GitHub - просто введите T
или нажмите Find file
и начните вводить имя командлета / концептуального раздела справки.
Export-CSV
добавляет кавычки независимо от типа. Вероятно, единственный способ сделать это - снова загрузить файл и использовать регулярные выражения для удаления этих кавычек:
(get-ChildItem -Path '*.txt').name | ForEach-Object {
Import-Csv -Path $_ -Delimiter "`t" |
Select-Object -Property Date,Value1 |
Export-Csv "out\$_"
(Get-Content $_) -replace ',"(\d+),(\d+)"$', ',$1.$2' | Set-Content "out\$_"
}
Примечание: вы можете установить -Encoding
для Set-Content
командлета!