Префикс каждой строки CSV с номером

Я унаследовал сценарий 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

префиксы должны начинаться с 0001 для каждого файла фрагмента или продолжаться с предыдущего фрагмента?

Santiago Squarzon 19.02.2024 20:48

Настоятельно рекомендуем включать имя в заголовок и запятую после номера строки. Это позволит многим существующим системам продолжать его корректную обработку. Но проблема, с которой вы сейчас столкнулись, заключается в том, что вам нужно прочитать и загрузить весь файл, чтобы узнать, сколько строк у вас есть, чтобы знать, сколько отступов нужно использовать. Это может существенно снизить производительность.

Joel Coehoorn 19.02.2024 20:52

Является ли проблема, которую вы пытаетесь решить, добавлением числа в начало строки, или это возможность как-то идентифицировать строку на более позднем этапе?

Andrew Morton 19.02.2024 20:55

@SantiagoSquarzon Я не совсем понимаю, что вы подразумеваете под «куском», но в нашем файле current_output.csv может быть 4000 строк. Я бы хотел, чтобы каждый из них имел префикс последовательного номера.

RKillcrazy 19.02.2024 21:06

@AndrewMorton Я пытаюсь понять, как поставить цифры на место.

RKillcrazy 19.02.2024 21:09

@JoelCoehoorn система, в которую в конечном итоге импортируются эти файлы, - это настоящая работа! Работать с ним ужасно. Это глючно! Это темперамент. Однако это то, что у нас есть, поэтому оно никуда не денется. Что касается производительности, я выполняю подобную работу на своей машине примерно раз в месяц, так что это не похоже на то, что сервер каждую минуту подвергается нагрузке из-за какой-то автоматизированной задачи. На мой взгляд, код мог бы подсчитать количество строк в файле, вычесть одну для заголовка, и именно так он знал бы, как далеко следует поставить префикс строк.

RKillcrazy 19.02.2024 21:13
$group.group | Export-Csv.... экспортирует фрагмент 40000 строк Csv в разные файлы, это то, что я имел в виду под фрагментом
Santiago Squarzon 19.02.2024 21:27

@SantiagoSquarzon Мне интересно, что делает эта часть кода. У меня никогда не было более одного файла, поэтому я никогда не знал. Тем не менее, в финальной [багги] системе с отдельными файлами можно работать только по одному, поэтому нумерация может начинаться заново для каждого файла.

RKillcrazy 19.02.2024 21:37

да, эта логика предназначена для разделения файлов на куски по 40 000 строк Csv, но сама логика чрезвычайно сложна и может быть намного проще

Santiago Squarzon 19.02.2024 21:52
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
103
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Добавлено несколько комментариев, которые, надеюсь, помогут вам понять логику кода, но следовать им может быть немного сложно. Использование 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
})

это сработало хорошо. У меня не было бы проблем с третьим столбцом, но система, с которой мы работаем, содержит ошибки и может использовать только столбцы ИМЯ и НОМЕР. У меня открыта заявка в их службу поддержки, в которой я жалуюсь на множество проблем, но я надеюсь, что этот код снимет немного стресса. Еще раз спасибо!

RKillcrazy 20.02.2024 16:58

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