scripts script resueltos programacion pasar parametros español ejercicios ejemplos linux bash shell

linux - resueltos - ¿Cómo puedo generar nuevos nombres de variables sobre la marcha en un script de shell?



shell script linux español (5)

El problema

Está utilizando el valor de i como si fuera un índice de matriz. No lo es, porque SAMPLE1 y SAMPLE2 son variables separadas, no una matriz.

Además, al llamar a echo SAMPLE{$i} , solo agrega el valor de i a la palabra "SAMPLE". La única variable que está eliminando referencias en esta declaración es $ i , por lo que obtuvo los resultados que obtuvo.

Maneras de abordar el problema

Hay dos formas principales de abordar esto:

  1. Desreferencia de varias etapas de una variable interpolada, a través de la expansión de variables integradas o indirectas .
  2. Iterando sobre una matriz, o usando i como un índice en una matriz.

Desreferencia con eval

Lo más fácil de hacer en esta situación es usar eval :

SAMPLE1=''1-first.with.custom.name'' SAMPLE2=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )); do eval echo /$SAMPLE${i} done

Esto agregará el valor de i al final de la variable, y luego volverá a procesar la línea resultante, expandiendo el nombre de la variable interpolada (por ejemplo, SAMPLE1 o SAMPLE2 ).

Desreferencia con variables indirectas

La respuesta aceptada para esta pregunta es:

SAMPLE1=''1-first.with.custom.name'' SAMPLE2=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )) do var="SAMPLE$i" echo ${!var} done

Esto es técnicamente un proceso de tres pasos. En primer lugar, asigna un nombre de variable interpolado a var , luego elimina el nombre de la variable almacenada en var y finalmente expande el resultado. Se ve un poco más limpio, y algunas personas se sienten más cómodas con esta sintaxis que con eval , pero el resultado es básicamente el mismo.

Iterando sobre una matriz

Puede simplificar tanto el ciclo como la expansión al iterar sobre una matriz en lugar de utilizar la interpolación variable. Por ejemplo:

SAMPLE=(''1-first.with.custom.name'' ''2-second.with.custom.name'') for i in "${SAMPLE[@]}"; do echo "$i" done

Esto ha agregado beneficios sobre los otros métodos. Específicamente:

  1. No necesita especificar una prueba compleja de bucle.
  2. Usted accede a elementos de matriz individuales a través de la sintaxis $ SAMPLE [$ i] .
  3. Puede obtener la cantidad total de elementos con la expansión de variable $ {# SAMPLE} .

Equivalencia práctica para el ejemplo original

Los tres métodos funcionarán para el ejemplo dado en la pregunta original, pero la solución de matriz proporciona la mayor flexibilidad general. Elija la que mejor funcione para los datos que tiene a mano.

Intento generar nombres dinámicos var en un script de shell para procesar un conjunto de archivos con nombres distintos en un bucle de la siguiente manera:

#!/bin/bash SAMPLE1=''1-first.with.custom.name'' SAMPLE2=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )) do echo SAMPLE{$i} done

Esperaría la salida:

1-first.with.custom.name 2-second.with.custom.name

pero tengo:

SAMPLE{1} SAMPLE{2}

¿Es posible generar nombres de Var en la marcha?


Necesitas utilizar la Indirección Variable:

SAMPLE1=''1-first.with.custom.name'' SAMPLE2=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )) do var="SAMPLE$i" echo ${!var} done

Desde la página de manual de Bash , bajo ''Expansión de parámetros'':

"Si el primer carácter del parámetro es un signo de exclamación (!), Se introduce un nivel de indirección variable. Bash usa el valor de la variable formada a partir del resto del parámetro como el nombre de la variable, esta variable se expande y luego el valor se usa en el resto de la sustitución, en lugar del valor del parámetro en sí. Esto se conoce como expansión indirecta ".


No es una respuesta independiente, solo una adición a la respuesta de Miquel, que no pude encajar bien en un comentario.

Puede llenar la matriz utilizando un bucle, el operador + = y un documento aquí también:

SAMPLE=() while read; do SAMPLE+=("$REPLY"); done <<EOF 1-first.with.custom.name 2-second.with.custom.name EOF

En bash 4.0, es tan simple como

readarray SAMPLE <<EOF 1-first.with.custom.name 2-second.with.custom.name EOF


Puede usar eval como se muestra a continuación:

SAMPLE1=''1-first.with.custom.name'' SAMPLE2=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )) do eval echo /$SAMPLE$i done


No por lo que yo sé, dijeron way @ johnshen64. Además, puedes resolver tu problema usando una matriz como esta:

SAMPLE[1]=''1-first.with.custom.name'' SAMPLE[2]=''2-second.with.custom.name'' for (( i = 1; i <= 2; i++ )) do echo ${SAMPLE[$i]} done

Tenga en cuenta que no necesita usar números como índices SAMPLE[hello] funcionará igual de bien