2009-08-12 24 views
5

Tengo un documento YAML como esto:¿Cómo puedo caminar un árbol YAML con Perl's YAML :: Tiny?

--- 
version: 1 
rootdirectory: 
    - subdirectory: 
    - file1 
    - file2 
    - subdirectory2 

que yo estoy cargando en un YAML :: Tiny objeto de esta manera:

$configuration = YAML::Tiny->read($configuration_file) 

veo de invocar el script con el depurador Perl que lo termino con un conjunto de hashes y arrays anidados que reflejan la estructura de la fuente YAML:

0 YAML::Tiny=ARRAY(0x84e3ba4) 
    0 HASH(0x80627dc) 
     'rootdirectory' => ARRAY(0x84e3d3c) 
     0 HASH(0x84352b0) 
      'subdirectory' => ARRAY(0x84e3df0) 
       0 'file1' 
       1 'file2' 
     1 'subdirectory2' 
     'version' => 1 

lo tanto, puedo hacer cosas como lo siguiente sin pr oblem:

print $configuration->[0]->{version} 

y recibe la respuesta esperada de '1'. Del mismo modo, también puedo hacer:

print $configuration->[0]->{rootdirectory}->[0]->{subdirectory}->[0] 

y recibir la respuesta esperada de 'archivo1'.

Mi problema proviene de todo el conocimiento a priori que necesito para derivar mi nombre de archivo en el ejemplo anterior. Como estoy tratando de permitir que los usuarios de mi script describan una estructura de directorios arbitraria en la configuración de YAML, esto no es suficiente. Necesito poder "caminar" el árbol desde 'rootdirectory'.

Por lo tanto, lo que hubiera imaginado que podría haber hecho algo como esto:

print keys($configuration->[0]) 

la que yo habría esperado de haber regresado 'RootDirectory, la versión' ... y así sucesivamente, interactuando sobre las matrices y hashes hasta que había caminado el árbol.

Cuando intento ejecutar el ejemplo anterior, me sale:

Type of arg 1 to keys must be hash (not array element) 

En este punto estoy atascado. Tal como lo entiendo, $ configuration -> [0], a pesar de ser un elemento de una matriz, es un elemento que contiene un hash que creo que debería poder invocar contra la función de las teclas.

¿Qué me falta aquí?

Respuesta

5

Trate

print "$_\n" for keys %{ $configuration->[0] }; 

Tienes que forzar el elemento de la matriz "$configuration->[0]" en una ref hash con "%{...}"

Así que para iterar sobre ellos:

for my $key (keys %{ $configuration->[0] }){ 
    my $value = $configuration->[0]{$key}; 

    print "$key => $value\n"; 
} 
+0

Excelente, gracias! Según tengo entendido, básicamente necesito algo de "azúcar sintáctico" en forma de% {$ configuración -> [0]} para forzar a Perl a creer que $ configuración -> [0] es en realidad un hash y no un elemento de matriz eso sucede que contiene un hash. ¿Es eso un comentario justo? –

+0

Sí –

+0

La palabra clave 'keys()' se define como 'keys (\%) {...}' lo que obliga a usar un hash, pero no elimina la desreferencia automática. –

3

YAML::Tiny crea una estructura de datos bastante compleja:

una referencia a un array llena de referencias a los hashes llena de referencias a las matrices de llena de referencias a los hashes ....

cuando $a es una referencia a una matriz, se accede a toda la matriz como @ $ a y los elementos como $$a[0], $$a[1], ... o alternativamente como $a->[0], $a->[1]

cuando $b es una referenc a un hash, que acceder a todo el hash como %$b y los elementos como $ $b{'somekey'}, $$b{'somekey'}, .... o alternativamente como $b->{'somekey'}, $b->{'somekey'}

cuando $configuration es una referencia a una matriz llena de referencias a hashes accede a toda la matriz como @$configuration, el primer elemento como $configuration->[0]. Se podía copiar que a otra variable

$firstconfig = $configuration->[0] 

y luego acceder a todo el hash como

%$firstconfig 

pero si quiere hacerlo de una sola vez que tiene que escribir el más complicado

%{ $configuration->[0] } 

Creo que esta es una de las cosas que se ha eliminado para Perl 6.

+0

Algo de eso ha * cambiado *, pero aún algo de eso existe en Perl6. –

+0

YAML :: Tiny simplemente reconstruye la estructura de datos serializados. La fuente de la complejidad es el documento YAML que se analiza. –

+0

Esto me ayudó muchísimo. He estado leyendo perlreftut y perldsc y he estado atrapado para siempre con referencias de matriz y hash y sin datos reales a la vista. Todavía no entiendo por completo, pero al menos puedo abrirme camino hacia la iluminación a partir de la respuesta. – djeikyb