Entonces tengo ini file y una función que analiza mi archivo:

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
}

Uso:

$iniFile = Parse-IniFile "myFile.ini"

Entonces, en caso de que mi archivo contenga una clave específica, por ejemplo "blabla", ¿cómo puedo obtener el valor?

Esto es lo que he intentado:

$value= $iniFile["blabla"]
2
user979033 14 dic. 2016 a las 12:06

2 respuestas

La mejor respuesta

Analizar un archivo INI produce una tabla hash de las secciones del archivo INI donde el valor de cada clave de sección es otra tabla hash con los pares clave / valor de la sección respectiva.

Básicamente, un archivo INI como este:

[something]
foo=23
bar=42

[other]
baz=5

Se convierte en una estructura de datos de tabla hash como esta:

@{
  'something' = @{
    'foo' = 23
    'bar' = 42
  }
  'other' = @{
    'baz' = 5
  }
}

Lo que debe hacer para obtener el valor de una clave en particular en una tabla hash anidada es verificar qué tabla hash anidada contiene una clave con ese nombre:

$iniFile.Keys | Where-Object {
  $iniFile[$_].ContainsKey('blabla')
} | ForEach-Object {
  $iniFile[$_]['blabla']
}
3
Ansgar Wiechers 14 dic. 2016 a las 09:45

En el modelo de datos de tabla hash elegido, necesita saber nombre (s) de sección para distinguir valores de propiedad para una clave de propiedad dada; este modelo de datos es el siguiente:

$y = @{ 'sectionname' = @{ 'propertykey' = 'propertyvalue' } }

Podría obtener acceso más directo (me atrevo a decir de primera mano ) a valores de propiedad para una clave de propiedad determinada utilizando modelo de datos de tabla hash invertida :

$x = @{ 'propertykey' = @{ 'sectionname' = 'propertyvalue' } }

La función Parse-FileIni en el siguiente fragmento de secuencia de comandos muestra la posible implementación de este último ( comentado para una mejor comprensión):

Function Parse-FileIni ($file)
{
    Function add_ini ( $auxadd )
    {
        if ( -not $ini.ContainsKey($name) )
        {
            $ini[$name] = @{}
        }
        $ini[$name][$section] = $value.Trim()
        if ( $auxadd ) { $aux[$section]++ }
    }
    $ini = @{}                         # create output object
    $aux = @{}                         # create properties counter for sections
    $section = '[]'          # section default name for out-of-sectionproperties

    #switch -regex -file $file         # garbles ANSI characters above 0x7F
                         # works for (plain) ASCII, UTF-8 and files with BOM
    switch -regex ( Get-Content $file )# -Encoding Default (i.e. ANSI)
    {
        '^\[(.+)\]$'                   # [section]
        {
            $section = $matches[1].Trim()
            if ( -not $aux.ContainsKey( $section ) ) {
                $aux[ $section ] = [int] 0
            }

        }

        '^\s*([^#\[;].+?)\s*=\s*(.*)'  # 'name=value'; works as well for 'name='
        {
            $name,$value = $matches[1..2]
            add_ini $true
        }
        '^\s*([^;\[#][^=]+?)$'         # name (omitted '=' or '=value')
        {
            $name = $matches[1].Trim()
            $value = ''
            add_ini $true
        }
    }
    $name,$value = '',''               # add empty sections
    $aux.Keys | ForEach-Object { 
            if ( $aux[$_] -eq 0 ) { 
                $section = $_
                add_ini $false
            }
        }
    $ini                               # return an object
}

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         
    switch -regex  ( Get-Content $file )
    {
        '^\[(.+)\]$'
        {
            $section = $matches[1].Trim()
            if (-not $ini.ContainsKey($section)) { $ini[$section] = @{} }
        }

        '^\s*([^#\[;].+?)\s*=\s*(.*)'
        {
            $name,$value = $matches[1..2]
            $ini[$section][$name] = $value.Trim()
        }
        '^\s*([^;\[#][^=]+?)$'
        {
            $name = $matches[1].Trim()
            $value = ''
            $ini[$section][$name] = $value.Trim()
        }
    }
    $ini
}

'-iniFile-'

$iniFile = ''
$iniFile = Parse-IniFile "d:\test\Google.ini"
$iniFile | Format-Table -AutoSize -Wrap

'-iniFili-'

$iniFili = ''
$iniFili = Parse-FileIni "d:\test\Google.ini"
$iniFili

Hice algunos cambios en la función Parse-IniFile original necesarios para analizar correctamente mi archivo .ini de prueba; para obtener una explicación, consulte los comentarios en el script anterior y el siguiente archivo Google.ini:

; PSPad configuration file for Google interface - adapted for testing
;; fake properties out of sections
foo="bar"
bubu=
; Search only pages in selected language
[Language]
Czech=lang_cz
English=lang_en
;; misunderstood (fake) use 
UK=English
; For search use selected Google server
[GoogleServer]
Česká Republika=www.google.cz
Österreich=www.google.at
UK=www.google.co.uk
;; multiple section declaration: simply merge their properties together
[Language]
German=lang_de
;; second occurrence of a property name: discard and override the first occurrence
Czech=lang_cs
;; fake empty section - somewhere in middle
[Client]
; Search only selected server
[ServerSearch]
;; only keys, no values, missing or present =
pspad.com
php.net=
w3.org
;; fake empty section - at the foot of file 
[Protocol]

El resultado muestra la diferencia :

PS D:\PShell> D:\PShell\SO\41138597_Parse-IniFile.ps1
-iniFile-
Name         Value                            
----         -----                            
_NO_SECTION  {bubu, foo}              
GoogleServer {UK, Česká Republika, Österreich}
Client       {}                               
Language     {English, German, UK, Czech}     
ServerSearch {w3.org, pspad.com, php.net}     
Protocol     {}                               

-iniFili-
Name            Value                   
----            -----                   
bubu            {[]}                    
UK              {GoogleServer, Language}
Czech           {Language}              
w3.org          {ServerSearch}          
php.net         {ServerSearch}          
Österreich      {GoogleServer}          
English         {Language}              
Česká Republika {GoogleServer}          
German          {Language}              
foo             {[]}                    
pspad.com       {ServerSearch}          
                {Client, Protocol}      

PS D:\PShell> $iniFili['UK']
Name                           Value                                                      
----                           -----                                                      
GoogleServer                   www.google.co.uk                                           
Language                       English                                                    

PS D:\PShell> $iniFili['UK']['GoogleServer']
www.google.co.uk
0
JosefZ 16 dic. 2016 a las 17:14