Saltar al contenido

Exportando un array en script bash

Esta división ha sido analizado por especialistas así garantizamos la veracidad de nuestro contenido.

Solución:

Es posible que las variables de matriz no se exporten (todavía).

Desde la página de manual de bash versión 4.1.5 bajo ubuntu 10.04.

La siguiente declaración de Chet Ramey (actual responsable de bash a partir de 2011) es probablemente la documentación más oficial sobre este “error”:

Realmente no hay una buena manera de codificar un array variable en el medio ambiente.

http://www.mail-archive.com/[email protected]/msg01774.html

TL; DR: las matrices exportables no son directamente admitido hasta bash-4.3 inclusive, pero puede exportar matrices (de manera efectiva) de una de estas dos formas:

  • una simple modificación a la forma en que se invocan los scripts secundarios
  • utilizar un función exportada para almacenar el array inicialización, con una simple modificación de los scripts secundarios

O puede esperar hasta que se publique bash-4.3 (en estado de desarrollo / RC a febrero de 2014, consulte ARRAY_EXPORT en el registro de cambios). Actualización: esta característica es no habilitado en 4.3. Si tu defines ARRAY_EXPORT al construir, la construcción fallará. El autor ha declarado que no está previsto completar esta función.


Lo primero que hay que entender es que el entorno bash (más propiamente entorno de ejecución de comandos) es diferente al concepto POSIX de un entorno. El entorno POSIX es una colección de name=value pares, y puede transmitirse de un proceso a sus hijos de varias formas (de hecho, una forma limitada de IPC).

El entorno de ejecución de bash es efectivamente un superconjunto de esto, con variables escritas, indicadores de solo lectura y exportables, matrices, funciones y más. Esto explica en parte por qué la salida de set (bash incorporado) y env o printenv diferir de.

Cuando usted invocar otro shell bash está iniciando un nuevo proceso, pierde algo de estado bash. Sin embargo, si obtiene una secuencia de comandos mediante puntos, la secuencia de comandos se ejecuta en el mismo entorno; o si ejecuta una subshell a través de ( ) el entorno también se conserva (porque bash se bifurca, conservando su estado completo, en lugar de reinicializarlo utilizando el entorno de proceso).


La limitación a la que se hace referencia en la respuesta de @ lesmana surge porque el entorno POSIX es simplemente name=value pares sin significado adicional, por lo que no hay una forma acordada de codificar o formatear variables escritas, vea a continuación una interesante peculiaridad de bash con respecto a las funciones y un próximo cambio en bash-4.3(propuesto array característica abandonada).

Hay un par de formas sencillas de hacer esto usando declare -p (incorporado) para generar parte del entorno bash como un conjunto de uno o más declare declaraciones que se pueden utilizar reconstruyen el tipo y el valor de un “nombre”. Esta es una serialización básica, pero con algo menos de la complejidad que implican algunas de las otras respuestas. declare -p conservas array índices, matrices dispersas y cotización de valores problemáticos. Para la serialización simple de un array podría simplemente volcar los valores línea por línea y usar read -a myarray para restaurarlo (funciona con matrices contiguas indexadas 0, ya que read -a asigna índices automáticamente).

Estos métodos no requieren ninguna modificación de las secuencias de comandos a las que está pasando las matrices.

declare -p array1 array2 > .bash_arrays       # serialise to an intermediate file
bash -c ". .bash_arrays; . otherscript.sh"    # source both in the same environment

Variaciones sobre lo anterior bash -c "..." Las formas a veces se usan (mal) en crontabs para establecer variables.

Las alternativas incluyen:

declare -p array1 array2 > .bash_arrays       # serialise to an intermediate file
BASH_ENV=.bash_arrays otherscript.sh          # non-interactive startup script

O, como una sola línea:

BASH_ENV=<(declare -p array1 array2) otherscript.sh

El ultimo usa sustitución de procesos para pasar la salida del declare comando como un script rc. (Este método solo funciona en bash-4.0 o posterior: versiones anteriores incondicionalmente fstat() rc archivos y use el tamaño devuelto a read() el archivo de una sola vez; un FIFO devuelve un tamaño de 0, por lo que no funcionará como se esperaba).

en un shell no interactivo (es decir, script de shell) el archivo al que apunta el BASH_ENV la variable se obtiene automáticamente. Debe asegurarse de que bash se invoque correctamente, posiblemente usando un shebang para invocar "bash" explícitamente, y no #!/bin/sh como bash no honrará BASH_ENV cuando está en modo histórico / POSIX.

Si todo tu array los nombres tienen un común prefix puedes usar declare -p $!myprefix* para expandir una lista de ellos, en lugar de enumerarlos.

Probablemente no debería intentar exportar y volver a importar el completo entorno bash utilizando este método, algunas variables y matrices especiales de bash son de solo lectura, y puede haber otros efectos secundarios al modificar variables especiales.

(También puede hacer algo un poco desagradable serializando el array definición a una variable exportable, y usando eval, pero no fomentemos el uso de eval ...

$ array=([1]=a [10]="b c")
$ export scalar_array=$(declare -p array)
$ bash # start a new shell
$ eval $scalar_array
$ declare -p array
declare -a array='([1]="a" [10]="b c")'

)


Como se mencionó anteriormente, hay una peculiaridad interesante: soporte especial para exportar funciones a través del entorno:

function myfoo() 
    echo foo

con export -f o set +a para habilitar este comportamiento, resultará en esto en el entorno (proceso), visible con printenv:

myfoo=()  echo foo

La variable es functionname (o functioname() para compatibilidad con versiones anteriores) y su valor es () functionbody . Cuando se inicia un proceso de bash posterior, se volverá a crear una función a partir de cada una de esas variables de entorno. Si echa un vistazo al archivo fuente de bash-4.2 variables.c verás variables que comienzan con () { se manejan especialmente. (Aunque crea una función usando esta sintaxis con declare -f está prohibido.) Actualizar: El problema de seguridad "shellshock" está relacionado con esta característica, los sistemas contemporáneos pueden deshabilitar la importación automática de funciones desde el entorno como mitigación.

Sin embargo, si sigues leyendo, verás un #if 0 (o #if ARRAY_EXPORT) código de protección que verifica las variables que comienzan con ([ and ending with ), and a comment stating "Array variables may not yet be exported". The good news is that in the current development version bash-4.3rc2 the ability to export indexed arrays (not associative) is enabled. This feature is not likely to be enabled, as noted above.

We can use this to create a function which restores any array data required:

% function sharearray() 
    array1=(a b c d)


% export -f sharearray 

% bash -c 'sharearray; echo $array1

'

Entonces, de manera similar al enfoque anterior, invoque el script secundario con:

bash -c "sharearray; . otherscript.sh"

O puede invocar condicionalmente el sharearray función en el script secundario agregando en algún punto apropiado:

[ "`type -t sharearray`" = "function" ] && sharearray

Tenga en cuenta que no hay declare -a en el sharearray función, si lo hace el array es implícitamente local a la función, que no es lo que se quiere. apoyos bash-4.2 declare -g que explícitamente hace que una variable sea global, de modo que (declare -ga) podría utilizarse entonces. (Dado que las matrices asociativas exigirdeclare -A no podrá utilizar este método para matrices asociativas antes de bash-4.2). parallel La documentación tiene una variación útil sobre este método, consulte la discusión de --env en la página de manual.


Su pregunta como está redactada también indica que puede estar teniendo problemas con export sí mismo. Puede exportar un nombre después de haberlo creado o modificado. "exportable" es una marca o propiedad de una variable, por conveniencia también puede establecer y exportar en una sola declaración. Hasta bash-4.2 export espera solo un nombre, ya sea una variable simple (escalar) o un nombre de función son compatibles.

Incluso si pudiera (en el futuro) exportar matrices, es posible que no se admita la exportación de índices seleccionados (un segmento) (aunque dado que las matrices son escasas, no hay ninguna razón por la que no se pueda permitir). Aunque bash también admite la sintaxis declare -a name[0], el subíndice se ignora y "nombre" es simplemente un índice normal array.

Dios. No sé por qué las otras respuestas hicieron esto tan complicado. Bash tiene soporte casi integrado para esto.

En el script de exportación:

myArray=( '  foo"bar  ' $'n''nbaz)' )  # an array with two nasty elements

myArray="$myArray[@]@Q" ./importing_script.sh

(Tenga en cuenta que las comillas dobles son necesarias para el manejo correcto de los espacios en blanco dentro de array elementos.)

Al entrar a importing_script.sh, el valor de la myArray La variable de entorno comprende estos 26 bytes exactos:

'  foo"bar  ' $'n\nbaz)'

Entonces lo siguiente reconstituirá el array:

eval "myArray=( $myArray )"

¡PRECAUCIÓN! No eval así si no puede confiar en la fuente de la myArray Variable ambiental. Este truco exhibe la vulnerabilidad "Little Bobby Tables". Imagínese si alguien estableciera el valor de myArray para ) ; rm -rf / #.

Sección de Reseñas y Valoraciones

Agradecemos que quieras sustentar nuestro quehacer exponiendo un comentario o valorándolo te damos la bienvenida.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *