Редактирование столбца в CSV

У меня есть CSV, содержащий более 24 000 имен серверов, а также другую информацию. Столбцы CSV - это Name, Group и Target. Пример исходных данных для столбца «Имя»:

WindowsAuthServer @ wddg9028WIN

Я пытаюсь найти способ отредактировать столбец Name в CSV. Мне нужно удалить WindowsAuthServer @ и WIN из имен серверов. Единственное, что я хочу оставить, это имя сервера, или wddg9028 в этом примере. Потенциальная проблема заключается в том, что не каждое имя сервера имеет этот формат, а некоторые содержат только имя сервера. Очевидно, что те, которые уже верны, не нужно менять, но я не уверен, что это сбивает с толку.

Я пробовал делать:

$test = $file.Name -replace "WindowsAuthServer @ ",""

Это возвращает имена именно так, как я хочу (за вычетом удаления WIN). Однако всякий раз, когда я это делаю, я теряю все остальные столбцы из CSV.

Есть ли способ отредактировать один столбец в CSV? Следует ли это делать во время чтения данных в этом случае?

Сегодня вы задали этот же вопрос три раза.

Maximilian Burszley 18.12.2018 22:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
45
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

С большие наборы данных, Команда конвейерный обычно предпочтительнее для сохранения постоянного использования памяти:

Import-Csv in.csv |
  Select-Object @{ 
      n='Name'
      e = { $_.Name -creplace 'WindowsAuthServer @ |WIN' }
    }, Group, Target |
      Export-Csv -NoTypeInformation -Encoding Utf8 out.csv

Таким образом, данные обрабатываются строка за строкой, и в качестве бонуса вы можете использовать Select-Object с расчетное свойство для выполнения преобразования вашего имени.


Тем не менее, если производительность имеет значение и, вы знаете, что можете разместить все данные в памяти сразу, вы можете использовать следующее (PSv4 +):

# Read the file in full into memory (transformed into objects).
$file = Import-Csv in.csv 

# Modify the `.Name` property values of the in-memory object collection.
$file.ForEach({ $_.Name = $_.Name -creplace 'WindowsAuthServer @ |WIN' })

# Export the in-memory object collection back to a CSV file.
$file | Export-Csv -NoTypeInformation -Encoding Utf8 out.csv

Что касается что ты пробовал:

$test = $file.Name -replace "WindowsAuthServer @ ",""

Этот оператор выполняет замену строк для всех значений свойств .Name и возвращает преобразованные строки как новые струны (которые вы затем назначаете $test).

Следовательно, ваши значения $file.Name остаются неизменный.

Вместо этого необходимо явно обновить свойства .Name. Хотя может возникнуть соблазн сделать следующее, нет работает:

# !! Does NOT work if $file is an *array* of objects.
$file.Name = $file.Name -replace "WindowsAuthServer @ ",""

То есть, хотя вы можете получить значения свойств массива объектов с простым доступом к свойству (.Name) - функция, называемая перечисление участников - свойства параметр, которые по дизайну не поддерживаются - см. эта проблема GitHub.

Вместо этого, помимо использования конвейера, как показано выше, у вас есть два варианта:

  • в PSv4 + вы можете использовать метод сбора .Where(), как показано выше.

  • в качестве альтернативы (также работает в более низких версиях PS) используйте цикл foreach, как показано в Ответ Ансгара Вихерса.

Пара тысяч строк с 3 полями в каждой - это далеко не то, что я бы назвал большим набором данных. ;)

Ansgar Wiechers 18.12.2018 22:00

@AnsgarWiechers: Ну, пара тысяч десять, но точка взята. Я надеюсь, что сопоставление этих двух подходов по-прежнему полезно.

mklement0 18.12.2018 22:04
Ответ принят как подходящий

Импортируйте CSV. Обработайте строки в цикле, заменив текущее значение рассматриваемого поля измененным значением. Экспортируйте данные обратно в CSV.

$csv = Import-Csv 'C:\path\to\input.csv'

foreach ($row in $csv) {
    $row.Name = $row.Name -replace 'WindowsAuthServer @ '
}

$csv | Export-Csv 'C:\path\to\output.csv' -NoType

По крайней мере, это ваш третий вопрос по теме. Найдите руководство по PowerShell. Это базовый материал В самом деле.

Спасибо, это то, что я искал. Я не уверен, почему, когда я пробовал $ row.Name = $ row.Name ... ранее, это не сработало. Может быть, я использовал двойные кавычки вместо одинарных?

JK72 18.12.2018 22:11

Нет, в данном случае двойные кавычки не должны иметь никакого значения.

Ansgar Wiechers 18.12.2018 22:19

@ JK72: $row.Name = $row.Name... работает, только если $row является строкой не замужем, как в этом ответе. Напротив, если $file содержит строки все, как следует из вашего вопроса, $file.Name = $file.Name... выполняет работу нет

mklement0 19.12.2018 00:07

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