Я унаследовал сценарий PS, который берет некоторые данные из CSV, форматирует их во что-то, что система может переварить, а затем сбрасывает обратно в другой CSV. Итак, я не до конца это понимаю; таким образом, я не знаю точно, куда вставить желаемый код/изменения. Это ужасная система, но это то, что мы имеем на данный момент. Ниже показано, что скрипт в настоящее время извлекает, манипулирует и затем выдает.
импорт.csv
Name,Number
John Smith,(555)123-4567
Jane Smith,(555)123-4567
Todd Smith,(555)123-4567
Как я уже упоминал, он выдает еще один CSV-файл, который импортируется в эту ужасную систему...
текущий_выход.csv
Name,Number
JohnSmith,5551234567
JaneSmith,5551234567
ToddSmith,5551234567
[Унаследованный] код, который делает это, приведен ниже:
$CSVDATA = import-csv *.csv
$people = @()
Foreach($person in $CSVDATA){
$namepattern = '[^a-zA-Z]'
$numberpattern = '[^0-9]'
if ($person.Name -ne "" -and $person.Number -ne ""){
$people += $myObject = [PSCustomObject]@{
Name = $($person.Name -replace $namepattern,'')
Number = $($person.Number -replace $numberpattern,'')
}
}
}
$counter = [pscustomobject] @{ Value = 0 }
$groupSize = 40000
$people = $people | where {$_.number -ne ""}
$groups = $people | Group-Object -Property { [math]::Floor($counter.Value++ / $groupSize) }
foreach($group in $groups){
$group.group | Export-Csv -NoTypeInformation -Encoding UTF8 -Delimiter "," -Path "..\Processed\$($group.name)-$(get-date -Format yyyy-MM-dd).csv"
$File = "..\Processed\$($group.name)-$(get-date -Format yyyy-MM-dd).csv"
(Get-Content $File) | Foreach-Object {
$_ -replace "`"", ""
} | Set-Content $File
}
Я хотел бы поставить перед каждой строкой номер строки, дополняя ее нулями, чтобы все выстраивалось в ряд в определенных представлениях. Как я уже упоминал, я не писал сценарий, поэтому не знаю точно, куда вставить то, что необходимо для создания желаемого результата ниже.
желаемый_выход.csv
Name,Number
0001JohnSmith,5551234567
0002JaneSmith,5551234567
0003ToddSmith,5551234567
Настоятельно рекомендуем включать имя в заголовок и запятую после номера строки. Это позволит многим существующим системам продолжать его корректную обработку. Но проблема, с которой вы сейчас столкнулись, заключается в том, что вам нужно прочитать и загрузить весь файл, чтобы узнать, сколько строк у вас есть, чтобы знать, сколько отступов нужно использовать. Это может существенно снизить производительность.
Является ли проблема, которую вы пытаетесь решить, добавлением числа в начало строки, или это возможность как-то идентифицировать строку на более позднем этапе?
@SantiagoSquarzon Я не совсем понимаю, что вы подразумеваете под «куском», но в нашем файле current_output.csv может быть 4000 строк. Я бы хотел, чтобы каждый из них имел префикс последовательного номера.
@AndrewMorton Я пытаюсь понять, как поставить цифры на место.
@JoelCoehoorn система, в которую в конечном итоге импортируются эти файлы, - это настоящая работа! Работать с ним ужасно. Это глючно! Это темперамент. Однако это то, что у нас есть, поэтому оно никуда не денется. Что касается производительности, я выполняю подобную работу на своей машине примерно раз в месяц, так что это не похоже на то, что сервер каждую минуту подвергается нагрузке из-за какой-то автоматизированной задачи. На мой взгляд, код мог бы подсчитать количество строк в файле, вычесть одну для заголовка, и именно так он знал бы, как далеко следует поставить префикс строк.
$group.group | Export-Csv.... экспортирует фрагмент 40000 строк Csv в разные файлы, это то, что я имел в виду под фрагментом
@SantiagoSquarzon Мне интересно, что делает эта часть кода. У меня никогда не было более одного файла, поэтому я никогда не знал. Тем не менее, в финальной [багги] системе с отдельными файлами можно работать только по одному, поэтому нумерация может начинаться заново для каждого файла.
да, эта логика предназначена для разделения файлов на куски по 40 000 строк Csv, но сама логика чрезвычайно сложна и может быть намного проще





Добавлено несколько комментариев, которые, надеюсь, помогут вам понять логику кода, но следовать им может быть немного сложно. Использование List<T> намного лучше, чем логика, которая у вас есть с Group-Object, для вывода фрагментов объектов в каждый CSV.
$csvdata = Import-Csv *.csv
$namepattern = '[^a-zA-Z]'
$numberpattern = '[^0-9]'
# this list is used to collect objects before outputting to a file
$chunk = [System.Collections.Generic.List[object]]::new()
# this variable determines how many objects to collect before outputting to a file
$groupSize = 40000
# this variable is used in the file name, before the hyphen (Processed\1-...., Processed\2-...., etc)
$idx = 1
# this variable is to add the numbers before the Names
$padding = 1
# this is the path that will be used to output each file, `{0}` gets replaced with the number in `$idx` later on
$File = "..\Processed\{0}-$(Get-Date -Format yyyy-MM-dd).csv"
foreach ($person in $csvdata) {
if ($person.Name -eq '' -or $person.Number -eq '') {
continue
}
# add the new object to the list
$chunk.Add([PSCustomObject]@{
# `($padding++).ToString().PadLeft(4, '0')` means that the number in `$padding` gets incremented by 1
# on each loop iteration and at the same time its outputted and concatenated with the `.Name` using zero padding
Name = ($padding++).ToString().PadLeft(4, '0') + ($person.Name -replace $namepattern)
Number = $person.Number -replace $numberpattern
})
# if the list has the same number of objects as the `$groupSize` variable
if ($chunk.Count -eq $groupSize) {
# create a new path incrementing `$idx` (-f injects the value of `$idx` in `{0}`)
$path = $File -f $idx++
# convert the chunk of objects to a Csv and remove all quotes `"`
($chunk.ToArray() | ConvertTo-Csv -NoTypeInformation) -replace '"' |
# output that to the new path
Set-Content $path
# clear the list
$chunk.Clear()
# and reset the padding variable
$padding = 1
}
}
# if there are any remaining objects in the list
if ($chunk.Count) {
# follow the same process as before
$path = $File -f $idx++
($chunk.ToArray() | ConvertTo-Csv -NoTypeInformation) -replace '"' |
Set-Content $path
$chunk.Clear()
}
Если вы хотите иметь CSV с тремя столбцами и иметь этот индекс в отдельном столбце, что было бы целесообразно, вам следует изменить:
$chunk.Add([PSCustomObject]@{
Name = ($padding++).ToString().PadLeft(4, '0') + ($person.Name -replace $namepattern)
Number = $person.Number -replace $numberpattern
})
К:
$chunk.Add([PSCustomObject]@{
Index = ($padding++).ToString().PadLeft(4, '0')
Name = $person.Name -replace $namepattern
Number = $person.Number -replace $numberpattern
})
это сработало хорошо. У меня не было бы проблем с третьим столбцом, но система, с которой мы работаем, содержит ошибки и может использовать только столбцы ИМЯ и НОМЕР. У меня открыта заявка в их службу поддержки, в которой я жалуюсь на множество проблем, но я надеюсь, что этот код снимет немного стресса. Еще раз спасибо!
префиксы должны начинаться с 0001 для каждого файла фрагмента или продолжаться с предыдущего фрагмента?