Así que estoy tratando de hacer algo, no estoy seguro de si es posible. Tengo el siguiente código:
for i in {0..5}; do if [[ -f ./user$i ]]; then group$i=$(grep -w "group" ./user0|awk '{print $2}'|perl -lape 's/\s+//sg')
Lo que quiero hacer es asignar una variable única para cada instancia de {0..5}, por lo que group1 group2 group3 group4 para cada nombre de variable. Luego cambiaría ./user0 a ./user$i y crearía una lista dinámica de variables basada en mi secuencia. es posible? Recibo el siguiente error cuando intento ejecutar esto y no estoy seguro de lo que realmente hice que a bash no le gusta.
test.sh: línea 16: group0=j: comando no encontrado
Kurt Stutsman proporciona el puntero correcto en un comentario sobre la pregunta: use matrices Bash para resolver su problema.
He aquí un ejemplo simplificado:
groups=() # declare an empty array; same as: declare -a groups for i in {0..5}; do groups[i]="group $i" # dynamically create element with index $i done # Print the resulting array's elements. printf '%s\n' "${groups[@]}"
Consulte la parte inferior de esta respuesta para conocer otras formas de enumerar los elementos de la matriz ${groups[@]}
.
Las matrices bash
se pueden expandir dinámicamente (e incluso pueden ser escasas ; los índices de los elementos no necesitan ser contiguos)
$i
funciona, sin dimensionar previamente la matriz. Tenga en cuenta que $i
no necesita tener el prefijo $
en el subíndice de matriz, porque los subíndices de matriz se evalúan en un contexto aritmético (el mismo contexto en el que se evalúan las expresiones $(( ... ))
).
En cuanto a lo que hiciste mal :
group$i=...
Bash no lo reconoce como una asignación de variable porque, tomado literalmente , group$i
no es un identificador válido (nombre de variable).
Debido a que no lo es, Bash continúa analizando hasta que se encuentra el siguiente metacarácter de shell y luego interpreta la palabra resultante como un comando para ejecutar, lo que en su caso resultó en el mensaje de error group0=j: command not found
.
Si, por alguna razón, no desea utilizar matrices para evitar este problema por completo, puede solucionar el problema :
Al involucrar un [comando] incorporado que declara variables como declare
, local
o export
, obliga a Bash a realizar expansiones primero , lo que expande group$i
a un nombre de variable válido antes de pasarlo al incorporado.
La respuesta de user2683246 demuestra el siguiente mejor enfoque mediante el uso de declare
(o, si se desean variables locales dentro de una función, local
) para crear las variables.
La respuesta de Soren usa export
, pero eso solo es recomendable si desea crear variables de entorno visibles para procesos secundarios en lugar de simples variables de shell .
Advertencia : con esta técnica, asegúrese de incluir entre comillas dobles la RHS para capturar el valor total; para ilustrar:
i=0; declare v$i=$(echo 'hi, there'); echo "$v0" # !! WRONG -> 'hi,': only UP TO 1ST SPACE i=0; declare v$i="$(echo 'hi, there')"; echo "$v0" # OK -> 'hi, there'
Otras formas de enumerar la matriz de groups
creada anteriormente:
# Enumerate array elements directly. for element in "${groups[@]}"; do echo "$element" done # Enumerate array elements by index. for (( i = 0; i < ${#groups[@]}; i++ )); do echo "#$i: ${groups[i]}" done
Use declare group$i=...
en lugar de solo group$i=...
Intente usar la función de exportación o declaración como esta
for i in {0..5}; do if [[ -f ./user$i ]]; then export group$i=$(grep -w "group" ......
con declarar
for i in {0..5}; do if [[ -f ./user$i ]]; then declare group$i=$(grep -w "group" ......
donde export
hace que el valor esté disponible para los subprocesos y declare
solo disponible dentro del mismo script.