Удалите запятые из чисел в CSV

У меня есть информация о папках для всех пользовательских папок. Он выгружается в файл CSV следующим образом:

Servername, F:\Users\user, 9,355.7602 MB, 264, 3054, 03/15/2000 13:28:48, 12/10/2018 11:58:29

Мы не можем работать с данными из-за разделителя тысяч в 3-м столбце. Я мог бы запустить сценарии отчета еще раз, но у нас много файловых серверов и большое количество пользователей, в частности, на одном, поэтому повторный запуск занимает очень много времени. Причина наличия запятых в том, что данные были записаны в виде строки, а не числа.

Я могу импортировать и конвертировать, единственная проблема в том, что любое число больше 1000 будет неправильным, и тогда все остальные данные будут отключены на 1 столбец. Я хотел бы заменить любую запятую между двумя числами. Не похоже, что это так сложно сделать с PowerShell, но мне не удалось ничего найти.

2 ответа

Решение

Если вы предполагаете, что столбцы данных разделены запятыми и пробелами и в ваших числах нет пробелов, вы можете использовать-replace оператор для этого.

$line = 'Servername, F:\Users\user, 9,355.7602 MB, 264, 3054, 03/15/2000 13:28:48, 12/10/2018 11:58:29'
$line -replace '(?<=\d),(?=\d)'

Если вы читаете данные из файла, вы можете прочитать данные с помощью Get-Content, заменить свои данные и обновить файл с помощью Set-Content.

(Get-Content file.csv) -replace '(?<=\d),(?=\d)' | Set-Content file.csv

Если файл большой, вы можете использовать более быстрый оператор переключения.

$data = switch -regex -file file.csv {
          '(?<=\d),(?=\d)' { $_ -replace '(?<=\d),(?=\d)' }
          default {$_}
        }
$data | Set-Content file.csv

Пояснение:

  • (?<=\d) использует утверждение положительного просмотра назад (?<=) что соответствует одной цифре \d.
  • (?=\d) использует утверждение положительного просмотра вперед (?=)что соответствует одной цифре. Вы можете заменить это на(?=\d{3}) чтобы соответствовать 3 цифрам подряд после запятой.
  • Поскольку вы хотите заменить целевую запятую пустой строкой, вам не нужна строка замены.

Как правило, лучше использовать команды, которые работают с данными или файлами CSV. Однако, если ваши данные содержат запятые и вы не квалифицируете свой текст, может быть трудно отличить данные от разделителей. Если у вас есть четкий способ провести это различие, вам лучше использовать ConvertFrom-Csv для уже прочитанных данных или Import-Csv для файлов. Вам нужно будет определить заголовки либо в файлах, либо в команде.

РЕДАКТИРОВАТЬ

По моему мнению, ,в наборе данных не разграничены, что приводит к тому, что этот ответ не работает должным образом, поскольку запятая рассматривается как разделитель столбцов при синтаксическом анализе CSV. Я собираюсь оставить его, поскольку он объясняет, как в целом управлять данными, как и следовало ожидать, если данные столбца были экранированным свойством. Однако ответ @AdminOfThings ниже должен работать для вашего конкретного случая здесь и исправит ошибочно определенный столбец, не полагаясь сначала на синтаксический анализ содержимого CSV как CSV.


Импортируйте данные с помощью Import-Csv, затем удалите все ,в третьем столбце. Это предполагает, что у вас нет значений, где, это десятичный разделитель:

Если у вас есть заголовки в CSV, вам не нужно определять имена заголовков или увлекаться написанием CSV:

Import-Csv -Path \path\to\file.csv | Foreach-Object {
  $_.ColumnName = $_.ColumnName -replace ','
} | Export-Csv -NoTypeInformation -Path \path\to\file.csv

Это работает так: мы импортируем CSV как рабочий PSCustomObject, затем для каждой строки мы берем любое имя столбца с размером и удаляем ,от него. Наконец, мы экспортируем измененныйPSCustomObject вернуться к исходному CSV.

Если у вас нет заголовков, это становится немного сложнее, поскольку мы должны определять временные заголовки, но Export-Csv нет возможности пропустить запись заголовков:

Import-Csv -Path \path\to\file.csv -Headers Col1, Col2, Col3, Col4, Col5, Col6, Col7 |
  Foreach-Object {
    $_.Col3 = $_.Col3 -replace ','
  } | ConvertTo-Csv | Select-Object -Skip 1 |
  Set-Content -Path \path\to\file.csv

Это делает то же самое, что и первый блок кода, но поскольку мы не хотим экспортировать временные заголовки, мы должны проявить творческий подход. Во-первых, обратите внимание, что мы ссылаемся на целевой столбец с временным именем заголовка. Вместо того, чтобы передавать измененный объект CSV прямо вExport-Csv, сначала мы хотим преобразовать объект в CSV, используя ConvertTo-Csv. Затем мы используемSelect-Objectчтобы пропустить первую строку преобразованного текста CSV, которая является заголовком, чтобы у нас были только данные строки и значения столбца. Наконец, мы используемSet-Content чтобы записать текст CSV без заголовка обратно в исходный файл.

Другие вопросы по тегам