代码之家  ›  专栏  ›  技术社区  ›  Brandon

PowerShell中的INI文件解析

  •  14
  • Brandon  · 技术社区  · 16 年前

    我正在分析PowerShell中的简单(无节)INI文件。这里是我提出的代码,有什么方法可以简化它吗?

    convertfrom-stringdata -StringData ( `
      get-content .\deploy.ini `
      | foreach-object `
        -Begin { $total = "" }  `
        { $total += "`n" + $_.ToString() } `
        -End { $total } `
    ).Replace("\", "\\")
    
    7 回复  |  直到 16 年前
        1
  •  28
  •   jpmc26    7 年前

    在互联网上搜索这个话题后,我找到了一些解决方案。所有这些都是手工解析文件数据,所以我放弃了尝试使用标准cmdlet来完成这项工作。有很多奇特的解决方案 this 它支持编写场景。

    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
    }
    

    这个是 Jacques Barathon 是的。

    跳过任何 name=value name starts with a semicolon ; which are comment lines $ini [$section] = @{} 具有 $ini[$section] = @{} .

        2
  •  10
  •   Steve Beckert    13 年前

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

    -join 将对象[]转换为单个字符串,数组中的每个项由换行符分隔。 ConvertFrom-StringData 然后将字符串解析为键/值对。

        3
  •  5
  •   WaffleSouffle    14 年前

    这实际上是对当前答案的扩展(似乎无法添加注释)。

    我把它弄得一团糟,只是为了对整数和小数进行基本的处理。。。

    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
    }
    
        4
  •  2
  •   dan-gph    14 年前

    Nini 例如

    Simple Example 从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")
    
        5
  •  1
  •   Community CDub    8 年前

    我优化了 this solution

    1. 为了保留注释和空行,我将它们放在一个特殊的键中。然后,在使用数据时可以忽略它们,或在写入文件时将其丢弃,如下面函数中所示 Set-IniFile
    2. 设置文件 使用选项 -PrintNoSection -PreserveNonData ,可以控制是否不应使用_节,以及是否应保留非数据行(与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
    ##
    
        6
  •  1
  •   Mark Wragg    8 年前

    我不确定您的源数据是什么样子,或者您的目标是什么。你到底在分析什么?你能发一份文件的样本吗?按原样,看起来您只是将回车连接到文件的现有行,并将\替换为\。

    $_.ToString() 自从 $_ 已是Get Content输出的字符串对象。

    ConvertFrom-StringData 是,但该cmdlet仅在PowerShell v2的预览中可用。

    如果您的文件看起来像。。。

    key1=value1
    key2=value2
    key3=value3
    

    那么你所需要的就是

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

    我不知道我是否理解你为什么要附加运费。也没有必要使用 -Begin -End 参数,至少从你发布的内容中我看不到。

        7
  •  0
  •   Steve Czetty Wilko van der Veen    12 年前

    动力壳碰撞

    第一步

    [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 
    
    推荐文章