Поместите каждый элемент из текстового файла в массив, но определите заголовки/заголовки

У меня есть текстовые файлы, содержащие

Firstname: xxx
Lastname: yyy
Login: abcd

Там есть много других записей для других определений, но все в том же формате header: data

Я хотел бы использовать массив в PowerShell для их чтения и хотел бы сделать

$array.firstname
$array.Login 

чтобы получить мне данные.

Можно ли это сделать?

В настоящее время мы используем длинное регулярное выражение для вывода данных, но оно становится громоздким, и мы хотели бы его упростить.

Содержит ли каждый файл только уникальные значения заголовков (например, только 1 строку входа в систему на файл)?

Mathias R. Jessen 26.07.2024 12:05

Пожалуйста, добавьте минимальный воспроизводимый пример к вашему вопросу. В качестве общего (нерегулярного) решения вы можете использовать ConvertFrom-String с собственным шаблоном.

iRon 26.07.2024 13:36
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Я хотел бы использовать массив в PowerShell для их чтения и хотел бы сделать

Массивы — это просто контейнеры фиксированного размера, кратные чему-то, сами по себе они ничего не делают.

Если вам нужна вещь, имеющая произвольные именованные свойства, такие как firstname или login, вам нужен собственный объект.

Вы можете использовать оператор регулярного выражения -match для идентификации и извлечения метки и значения в каждой строке, например:

$filePath = 'C:\path\to\file.txt'

# create an ordered dictionary to temporarily hold the label-value pairs
$properties = [ordered]@{}

# read the file into memory line-by-line
Get-Content $filePath |ForEach-Object {
  # test whether the line matches the `label: value` format
  if ($_ -match '^([^:]+):\s*(.*)$') {
    # ... and if so, extract the values matched by the capture groups
    $properties[$Matches[1]] = $Matches[2]
  }
}

# finally convert the ordered dictionary to an object
$myObject = [pscustomobject]$properties

$myObject теперь содержит объект со свойствами, названными в честь меток заголовков, найденных в файле, поэтому теперь вы можете ссылаться на $myObject.Login и т. д.


Если вы хотите вообще избежать регулярных выражений, используйте String.Split() вместо -match+$Matches:

# read the file into memory line-by-line
Get-Content $filePath |ForEach-Object {
  # test whether the line has a `:`
  if ($_ -like '*:*') {
    $label,$value = $_.Split(':', 2) |ForEach-Object Trim
    $properties[$label] = $value
  }
}

Это именно то, что мы используем, и я хотел бы отойти от регулярных выражений

Billy Smith 26.07.2024 12:25

@BillySmith Я думал, ты хочешь отойти от громоздкого шаблона регулярных выражений - ^([^:]+):\s*(.*)$ слишком много?

Mathias R. Jessen 26.07.2024 12:26

Действительно, этот код string.Split() получает индекс Cannot в нулевой массив.

Billy Smith 26.07.2024 13:56

@BillySmith, второй пример - это частичный фрагмент, вам все равно нужно заранее определить $properties = [ordered]@{}

Mathias R. Jessen 26.07.2024 14:03

Привет, Матиас! Я ценю твою помощь, теперь я получаю все объекты в $properties.Firstname.

Billy Smith 26.07.2024 14:17

Возможно, вы случайно добавили параметр -Raw при вызове Get-Content?

Mathias R. Jessen 26.07.2024 14:31

Да, -raw используется get-content, и если я загружаю файл в Notepad++, я вижу CRLF в конце каждой строки. Удалил -raw и все заработало

Billy Smith 26.07.2024 15:01

ConvertFrom-StringData

В Powershell 5.1 вы не можете указать разделитель. Он ожидает = в качестве разделителя, поэтому сначала замените : на =. Если в строке несколько :, мы заменим только первое вхождение, используя регулярные выражения и группы захвата.

$hashtable = (Get-Content .\data.txt -Raw) -replace '(?m)^(.*?):(.*$)', '$1=$2' | ConvertFrom-StringData
$hashtable.Login
$hashtable.Firstname
$hashtable.Lastname

В PowerShell 7+ был введен параметр -Delimiter.

$hashtable = Get-Content .\data.txt -Raw | ConvertFrom-StringData -Delimiter ':' 
$hashtable.Login
$hashtable.Firstname
$hashtable.Lastname

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