Инициализация файла INI в PowerShell

Я разбираю простой (без разделов) INI-файл в PowerShell. Вот код, который я придумал, есть ли способ его упростить?

convertfrom-stringdata -StringData ( ` get-content .\deploy.ini ` | foreach-object ` -Begin { $total = "" } ` { $total += "`n" + $_.ToString() } ` -End { $total } ` ).Replace("\", "\\") 

После поиска в Интернете по этой теме я нашел несколько решений. Все они представляют собой ручной анализ файлов, поэтому я отказался от попыток сделать стандартные командлеты для выполнения этой задачи. Есть модные решения, которые поддерживают сценарий написания.

Есть более простые, и если мне не нужна поддержка записи, я выбрал следующий очень элегантный fragment кода:

 Function Parse-IniFile ($file) { $ini = @{} # Create a default section if none exist in the file. Like a java prop file. $section = "NO_SECTION" $ini[$section] = @{} switch -regex -file $file { "^\[(.+)\]$" { $section = $matches[1].Trim() $ini[$section] = @{} } "^\s*([^#].+?)\s*=\s*(.*)" { $name,$value = $matches[1..2] # skip comments that start with semicolon: if (!($name.StartsWith(";"))) { $ini[$section][$name] = $value.Trim() } } } $ini } 

Это Жак Баратон .

Обновление Благодаря Aasmund Eldhuset и @msorens для улучшений: обрезка пробелов и поддержка комментариев.

Обновить 2 Пропустить любые пары name=value где name начинается с точки с запятой ; которые представляют собой строки комментариев . Заменил $ini [$section] = @{} на $ini[$section] = @{} .

Дон Джонс почти все правильно. Пытаться:

 ConvertFrom-StringData((Get-Content .\deploy.ini) -join "`n") 

-join преобразует Object [] в одну строку, причем каждый элемент массива разделяется символом новой строки. ConvertFrom-StringData затем анализирует строку в пары ключ / значение.

Это действительно расширение для текущего ответа (похоже, не добавляет комментарий).

Я испортил это, чтобы выполнить рудиментарное обращение с целыми числами и десятичными знаками …

 function Parse-IniFile ($file) { $ini = @{} switch -regex -file $file { #Section. "^\[(.+)\]$" { $section = $matches[1].Trim() $ini[$section] = @{} continue } #Int. "^\s*([^#].+?)\s*=\s*(\d+)\s*$" { $name,$value = $matches[1..2] $ini[$section][$name] = [int]$value continue } #Decimal. "^\s*([^#].+?)\s*=\s*(\d+\.\d+)\s*$" { $name,$value = $matches[1..2] $ini[$section][$name] = [decimal]$value continue } #Everything else. "^\s*([^#].+?)\s*=\s*(.*)" { $name,$value = $matches[1..2] $ini[$section][$name] = $value.Trim() } } $ini } 

Одна из возможностей – использовать библиотеку .NET ini. Например, Нини .

Я перевел Простой пример из документов Nini в PowerShell ниже. Вам нужно поместить файл nini.dll в тот же каталог, что и скрипт.

 $scriptDir = Split-Path -parent $MyInvocation.MyCommand.Definition Add-Type -path $scriptDir\nini.dll $source = New-Object Nini.Config.IniConfigSource("e:\scratch\MyApp.ini") $fileName = $source.Configs["Logging"].Get("File Name") $columns = $source.Configs["Logging"].GetInt("MessageColumns") $fileSize = $source.Configs["Logging"].GetLong("MaxFileSize") 

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

  1. Я сделал упорядоченный словарь из исходного словаря (хеш-таблицы), чтобы иметь возможность сохранить структуру файла
  2. И чтобы сохранить комментарии и пустые строки, я помещаю их в специальный ключ. Затем они могут игнорироваться при использовании данных или отбрасываться при записи в файл, как показано ниже в функции Set-IniFile
  3. В Set-IniFile с использованием опций -PrintNoSection и -PrintNoSection его можно контролировать, если NO_SECTION следует использовать, и если строки не-данных (не соответствующие key = value или [section] должны быть сохранены.

 Function Get-IniFile ($file) # Based on "https://stackoverflow.com/a/422529" { $ini = [ordered]@{} # Create a default section if none exist in the file. Like a java prop file. $section = "NO_SECTION" $ini[$section] = [ordered]@{} switch -regex -file $file { "^\[(.+)\]$" { $section = $matches[1].Trim() $ini[$section] = [ordered]@{} } "^\s*(.+?)\s*=\s*(.*)" { $name,$value = $matches[1..2] $ini[$section][$name] = $value.Trim() } default { $ini[$section]["<$("{0:d4}" -f $CommentCount++)>"] = $_ } } $ini } Function Set-IniFile ($iniObject, $Path, $PrintNoSection=$false, $PreserveNonData=$true) { # Based on "http://www.out-web.net/?p=109" $Content = @() ForEach ($Category in $iniObject.Keys) { if ( ($Category -notlike 'NO_SECTION') -or $PrintNoSection ) { # Put a newline before category as seperator, only if there is none $seperator = if ($Content[$Content.Count - 1] -eq "") {} else { "`n" } $Content += $seperator + "[$Category]"; } ForEach ($Key in $iniObject.$Category.Keys) { if ( $Key.StartsWith('<') ) { if ($PreserveNonData) { $Content += $iniObject.$Category.$Key } } else { $Content += "$Key = " + $iniObject.$Category.$Key } } } $Content | Set-Content $Path -Force } ### EXAMPLE ## ## $iniObj = Get-IniFile 'c:\myfile.ini' ## ## $iniObj.existingCategory1.exisitingKey = 'value0' ## $iniObj['newCategory'] = @{ ## 'newKey1' = 'value1'; ## 'newKey2' = 'value2' ## } ## $iniObj.existingCategory1.insert(0, 'keyAtFirstPlace', 'value3') ## $iniObj.remove('existingCategory2') ## ## Set-IniFile $iniObj 'c:\myNewfile.ini' -PreserveNonData $false ## 

Я не совсем уверен, как выглядят ваши исходные данные или какова ваша цель. Для чего вы разбираетесь? Можете ли вы опубликовать образец файла? Как есть, похоже, что вы просто конкатенируете возврат каретки к существующим строкам файла и заменяете \ на \.

Непонятно, почему вы используете $_.ToString() поскольку $_ уже является строковым объектом, выводимым Get-Content.

Является ли цель просто взять файл, содержащий пару пар name = value, и преобразовать его в хеш-таблицу? Это то, что ConvertFrom-StringData , хотя этот командлет доступен только в предварительном просмотре PowerShell v2.

Если ваш файл выглядит так …

 key1=value1 key2=value2 key3=value3 

Тогда все, что вам нужно, это

 ConvertFrom-StringData (Get-Content .\deploy.ini) 

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

nini выглядит как библиотека … не уверен в powershell

сбой PowerShell

первый шаг

 [void][system.reflection.assembly]::loadfrom("nini.dll") (refer add-type now in ps2 ) 

после его использования

 $iniwr = new-object nini.config.iniconfigsource("...\ODBCINST.INI") $iniwr.Configs et boom 
  • Могу ли я получить && для работы в Powershell?
  • Linux «Top» для Windows Powershell?
  • Программно ассоциировать расширения файлов с приложением в Windows
  • Удаление файлов старше 15 дней с помощью PowerShell
  • Массовое преобразование фотографий в меньший размер?
  • Неверный размер шрифта Powershell на Windows 8.1
  • Как настроить Windows на виртуальной машине с помощью Powershell (Hyper-V)
  • Ожидание ввода пользователя с тайм-аутом
  • Как я могу найти GUID продукта установленной установки MSI?
  • Сценарий PowerShell для проверки приложения, которое блокирует файл?
  • Windows PowerShell эквивалентна Unix / Linux `pwd`?
  • Давайте будем гением компьютера.