Как использовать переменную в качестве части имени массива

usermod команда позволит Вам изменять основную группу пользователя, дополнительную группу или много других атрибутов. -g переключитесь управляет основной группой.

Для Ваших других вопросов...

  1. Если Вы указываете группу, groupname, это не существует во время useradd этап, Вы получите ошибку - useradd: неизвестная группа groupname

  2. groupadd команда создает новые группы.

  3. Группа останется, если Вы удалите всех пользователей, содержавших в. Необходимо не обязательно удалить пустую группу.

  4. Создайте hilbert группа через groupadd hilbert. Затем переместите использование основной группы David usermod -g hilbert hilbert. (Обратите внимание на то, что первое hilbert название группы и второе hilbert имя пользователя. Это важно в случаях, куда Вы перемещаете пользователя к группе с другим именем),

Можно усложнять вещи немного здесь, все же. Во многих дистрибутивах Linux, простом useradd hilbert создаст пользователя hilbert и группа того же имени как основное устройство. Я добавил бы дополнительные группы, указанные вместе с помощью -G переключатель.

11
08.01.2013, 00:28
7 ответов

Попытайтесь делать это:

$ arrayA=(1 2 3)
$ x=A
$ var=array$x[@]
$ echo ${!var}
1 2 3

Примечание:

  • от man bash (расширение параметра):
    ${parameter}
           The value of parameter is substituted.
 The braces are required when parameter is a positional parameter with
  more than one

цифра, или когда параметр сопровождается символом, который не должен быть интерпретирован как часть его имени.
*, Если первый символ параметра является восклицательным знаком (!), уровень переменной абстракции представлен. Bash использует значение переменной, сформированной из остальной части параметра как название переменной; эта переменная затем расширена, и то значение используется в остальной части замены, а не значения самого параметра. Это известно как косвенное расширение. * Исключениями к этому являются расширения $ {! prefix*} и $ {! имя} описанный ниже. Восклицательный знак должен сразу следовать за левой фигурной скобкой для представления косвенности.

20
27.01.2020, 19:57
  • 1
    Что точно ! выполнение перед var переменная? Как это работает, это, казалось, было заменой истории относительно поиска с помощью Google, но я не мог видеть, как это работало здесь. –  Aaron 08.01.2013, 00:44
  • 2
    Посмотрите мой отредактированный –  Gilles Quenot 08.01.2013, 00:53

никакой путь :(

если Ваши массивы настолько просты, то используйте ассоциативные массивы

    declare -A array
    array[A]="1 2 3"
    array[B]="a b c"

к сожалению, если Ваши массивы более сложны (например, array=( "a b" c ) ), это не работало бы. Затем необходимо думать тяжелее о другом способе достигнуть цели.

-1
27.01.2020, 19:57
  • 1
    Какова причина downvote? Ассоциативный массив обеспечивает хороший способ сгруппировать все, предполагая, что мои элементы не будут все содержать пространства. –  Aaron 08.01.2013, 01:45
  • 2
    @Aaron, Принимающий Ваши элементы, не содержит пробелы, который является разумным дизайном. @watael я предполагаю начало ответа с “никаким путем”, когда основное внимание Вашего вопроса явно возможно, не был хорошей идеей. –  Gilles 'SO- stop being evil' 08.01.2013, 02:12
[1120154]Используйте [1120733]eval[12180]
-1
27.01.2020, 19:57

Таким образом можно создать переменную с динамическим именем (версия bash <4.3).

# Dynamically named array
my_variable_name="dyn_arr_names"
eval $my_variable_name=\(\)

# Adding by index to the array eg. dyn_arr_names[0]="bob"
eval $my_variable_name[0]="bob"

# Adding by pushing onto the array eg. dyn_arr_names+=(robert)
eval $my_variable_name+=\(robert\)

# Print value stored at index indirect
echo ${!my_variable_name[0]}

# Print value stored at index
eval echo \${$my_variable_name[0]}

# Get item count
eval echo \${#$my_variable_name[@]}

Ниже представлена ​​группа функций, которые можно использовать для управления массивами с динамическими именами (версия bash <4.3).

# Dynamically create an array by name
function arr() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
     # The following line can be replaced with 'declare -ag $1=\(\)'
     # Note: For some reason when using 'declare -ag $1' without the parentheses will make 'declare -p' fail
    eval $1=\(\)
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval $1[\$\(\(\${#${1}[@]}\)\)]=\$2
}

# Update an index by position
function arr_set() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval ${1}[${2}]=\${3}
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    eval echo \${${1}[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    local v=$1
    local i=$2
    local max=$(eval echo \${\#${1}[@]})
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        eval echo \${$v[$i]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    local v=${1}
    eval echo \${\#${1}[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep "a dyn_"

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

Ниже представлена ​​группа функций, которые можно использовать для управления массивами с динамическими именами (версия bash> = 4.3).

# Dynamically create an array by name
function arr() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -g -a $1=\(\)   
}

# Insert incrementing by incrementing index eg. array+=(data)
function arr_insert() { 
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1
    r[${#r[@]}]=$2
}

# Update an index by position
function arr_set() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1 
    r[$2]=$3
}

# Get the array content ${array[@]}
function arr_get() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1 
    echo ${r[@]}
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_at() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable" 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    [[ ! "$2" =~ ^(0|[-]?[1-9]+[0-9]*)$ ]] && { echo "Array index must be a number" 1>&2 ; return 1 ; }
    declare -n r=$1 
    local max=${#r[@]}
    # Array has items and index is in range
    if [[ $max -gt 0 && $i -ge 0 && $i -lt $max ]]
    then 
        echo ${r[$2]}
    fi
}

# Get the value stored at a specific index eg. ${array[0]}  
function arr_count() {
    [[ ! "$1" =~ ^[a-zA-Z_]+[a-zA-Z0-9_]*$ ]] && { echo "Invalid bash variable " 1>&2 ; return 1 ; }
    declare -p "$1" > /dev/null 2>&1
    [[ $? -eq 1 ]] && { echo "Bash variable [${1}] doesn't exist" 1>&2 ; return 1 ; }
    declare -n r=$1
    echo ${#r[@]}
}



array_names=(bob jane dick)

for name in "${array_names[@]}"
do
    arr dyn_$name
done

echo "Arrays Created"
declare -a | grep "a dyn_"

# Insert three items per array
for name in "${array_names[@]}"
do
    echo "Inserting dyn_$name abc"
    arr_insert dyn_$name "abc"
    echo "Inserting dyn_$name def"
    arr_insert dyn_$name "def"
    echo "Inserting dyn_$name ghi"
    arr_insert dyn_$name "ghi"
done

for name in "${array_names[@]}"
do
    echo "Setting dyn_$name[0]=first"
    arr_set dyn_$name 0 "first"
    echo "Setting dyn_$name[2]=third"
    arr_set dyn_$name 2 "third"
done 

declare -a | grep 'a dyn_'

for name in "${array_names[@]}"
do
    arr_get dyn_$name
done


for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name by index"
    # Print by index
    for (( i=0 ; i < $(arr_count dyn_$name) ; i++ ))
    do
        echo "dyn_$name[$i]: $(arr_at dyn_$name $i)"

    done
done

for name in "${array_names[@]}"
do
    echo "Dumping dyn_$name"
    for n in $(arr_get dyn_$name)
    do
        echo $n
    done
done

Для получения более подробной информации об этих примерах посетите Getting Bashed by Dynamic Arrays, автор Ludvik Jerabek

-1
27.01.2020, 19:57

Esto requirió mucho ensayo y error, pero finalmente funcionó.

Me inspiré un poco en Youness. Pero todas las demás respuestas no ayudaron en mi bash anterior (suse11sp1 [3.2.51 (1 )-release])

El ciclo 'for' se negó a expandir la matriz indirecta, en su lugar, debe expandirlo previamente -, utilícelo para crear otra matriz con su nuevo nombre de variable. Mi ejemplo a continuación muestra un bucle doble, ya que ese es mi uso previsto.

THEBIGLOOP=(New_FOO New_BAR)

FOOthings=(1 2 3)
BARthings=(a b c)

for j in ${THEBIGLOOP[*]}
do
    TheNewVariable=$(eval echo \${${j#New_}things[@]})

    for i in $TheNewVariable
        do
            echo  $j $i" hello"
        echo
    done
done

Estoy usando #para eliminar el "Nuevo _" de la primera entrada de matriz, luego lo concateno con "cosas", para obtener "FOOcosas". \${} con echo y eval, luego hacen lo suyo en orden sin arrojar errores, que se envuelve en un nuevo $ ()y se le asigna el nuevo nombre de variable.

$ Test.sh

New_FOO 1 hello

New_FOO 2 hello

New_FOO 3 hello

New_BAR a hello

New_BAR b hello

New_BAR c hello
ACTUALIZACIÓN #####2018/06/07

Recientemente descubrí un giro más en este tema. La variable creada no es en realidad una matriz, sino una cadena delimitada por espacios. Para la tarea anterior, estuvo bien, debido a cómo funciona "for", no lee la matriz, se expande y luego se repite, vea el extracto a continuación:

for VARIABLE in 1 2 3 4 5.. N
do
    command1
    command2
    commandN
done

Pero, luego necesitaba usarlo como una matriz. Para esto necesitaba realizar un paso más. Tomé el código textualmente por Dennis Williamson . Lo he probado y funciona bien.

IFS=', ' read -r -a TheNewVariable <<< ${TheNewVariable[@]}

El "IFS=', '" es una variable que contiene su delimitador. "leer" con "-a" corta y devuelve la picadura a la variable de matriz. Tenga en cuenta que esto no respeta las comillas, pero hay algunas opciones en read para administrar esto, p. Eliminé la bandera -r que no necesitaba. Así que ahora he combinado esta adición en la creación de variables, lo que permite que los datos se traten y direccionen como se debe.

THEBIGLOOP=(New_FOO New_BAR)

FOOthings=(1 2 3)
BARthings=(a b c)

for j in ${THEBIGLOOP[*]}
do

    IFS=', ' read -a TheNewVariable <<< $(eval echo \${${j#New_}things[@]})

    for i in ${TheNewVariable[@]}  #Now have to wrap with {} and expand with @
        do
            echo  $j $i" hello"
            echo  ${TheNewVariable[$i]}  #This would not work in the original code
        echo
    done
done
3
27.01.2020, 19:57

Хотя вы можете использовать непрямой доступ, как указано в другом ответе , другим способом (в ksh и Bash 4.3 и новее )будет использование имен. Особенно в случае массивов это может быть более полезным, поскольку вы можете индексировать массив через nameref и не нужно помещать индекс в переменную, используемую в качестве ссылки.

arr1=(a b c)
arr2=(x y z)
typeset -n p=arr1    # or 'declare -n' 
echo "${p[1]}"       # prints 'b'

Непрямой доступ не работает:

q=arr2
echo "${!q}"         # prints 'x', the same as $arr2
echo "${!q[1]}"      # doesn't work, it tries to take q[1] as a reference

Как мог бы сказать программист на C, ${!q[1]}здесь действует так, как если бы qбыл массивом указателей, а не указателем на массив.

6
27.01.2020, 19:57

Мне помогло:

У меня есть массивы, объявленные глобальными из формы:

declare -a total_count
declare -a total_min
declare -a total_max
declare -a total_med
declare -a total_avg
declare -a total_stdev

И я хочу распечатать таблицу, состоящую из содержимого вышеупомянутых массивов, без необходимости выполнять одну и ту же работу снова и снова.

Я хочу, чтобы функция получала префикс имени массива и количество строк, которые я хочу напечатать, и делала все остальное. Основная проблема здесь заключалась в том, чтобы получить доступ к массиву bash по определенному индексу с именем массива, состоящим из функциональной переменной.

Я заметил, что использование evalдважды может сделать работу. Без этого трюка я увидел ошибку «плохая замена».

function print_table {
    name=$1
    len=$2

    # print banner
    echo -n "filename "
    for col in _count _min _max _med _avg _stdev
    do
        echo -n "${name}${col} "
    done
    echo ""

    #print data
    for ((i=0;i<len;i++)); do
        line="count=\$\{${name}_count[$i]\}"
        eval "$line"
        line="min=\$\{${name}_min[$i]\}"
        eval "$line"
        line="max=\$\{${name}_max[$i]\}"
        eval "$line"
        line="med=\$\{${name}_med[$i]\}"
        eval "$line"
        line="avg=\$\{${name}_avg[$i]\}"
        eval "$line"
        line="stdev=\$\{${name}_stdev[$i]\}"
        eval "$line"
        eval "printf \"%s %d %f %f %f %f %f \n\" \"${filename[$i]}\" \"$count\" \"$min\" \"$max\" \"$med\" \"$avg\" \"$stdev\" "
    done
}

0
26.05.2020, 12:18

Теги

Похожие вопросы