Подтвердить что ты не робот

Как скопировать массив в Bash?

У меня есть массив приложений, инициализированных так:

depends=$(cat ~/Depends.txt)

Когда я пытаюсь разобрать список и скопировать его в новый массив, используя,

for i in "${depends[@]}"; do
   if [ $i #isn't installed ]; then
      newDepends+=("$i")
   fi
done

Что происходит, так это то, что только первый элемент зависит от newDepends.

for i in "${newDepends[@]}"; do
   echo $i
done

^^ Это выведет только одну вещь. Поэтому я пытаюсь понять, почему мой цикл for только перемещает первый элемент. Весь список изначально зависит, так что это не так, но у меня нет идей.

4b9b3361

Ответ 1

a=(foo bar "foo 1" "bar two")  #create an array
b=("${a[@]}")                  #copy the array in another one 

for value in "${b[@]}" ; do    #print the new array 
echo "$value" 
done   

Ответ 2

Самый простой способ скопировать неассоциативный массив в bash - это:

arrayClone=("${oldArray[@]}")

или добавить элементы в предсуществующий массив:

someArray+=("${oldArray[@]}")

Новые строки/пробелы/IFS в элементах будут сохранены.

Для копирования ассоциативных массивов решения Isaac отлично работают.

Ответ 3

Решения, указанные в других ответах, не будут работать для ассоциативных массивов или для массивов с несмежными индексами. Вот более общее решение:

declare -A arr=([this]=hello [\'that\']=world [theother]='and "goodbye"!')
temp=$(declare -p arr)
eval "${temp/arr=/newarr=}"

diff <(echo "$temp") <(declare -p newarr | sed 's/newarr=/arr=/')
# no output

И еще:

declare -A arr=([this]=hello [\'that\']=world [theother]='and "goodbye"!')
declare -A newarr
for idx in "${!arr[@]}"; do
    newarr[$idx]=${arr[$idx]}
done

diff <(echo "$temp") <(declare -p newarr | sed 's/newarr=/arr=/')
# no output

Ответ 4

Начиная с Bash 4.3, вы можете сделать это

$ alpha=(bravo charlie 'delta  3' '' foxtrot)

$ declare -n golf=alpha

$ echo "${golf[2]}"
delta  3

Ответ 5

Вы можете скопировать массив, вставив элементы первого массива в копию, указав индекс:

#!/bin/bash

array=( One Two Three Go! );
array_copy( );

let j=0;
for (( i=0; i<${#array[@]}; i++)
do
    if [[ $i -ne 1 ]]; then # change the test here to your 'isn't installed' test
        array_copy[$j]="${array[$i]}
        let i+=1;
    fi
done

for k in "${array_copy[@]}"; do
    echo $k
done

Результатом этого будет:

One
Three
Go!

Полезный документ на bash массивах находится на TLDP.

Ответ 6

Проблема в том, чтобы скопировать массив в функцию, чтобы он был виден в родительском коде. Это решение работает для индексированных массивов и, если перед копированием предварительно определены как declare -A ARRAY, работает также для ассоциативных массивов.

function array_copy
# $1 original array name
# $2 new array name with the same content
{
    local INDEX
    for INDEX in $(eval echo "\${!$1[@]}")
    do
        eval "$2[\"$INDEX\"]=\"\${$1[$INDEX]}\""
    done
}

Ответ 7

Попробуйте это: arrayClone=("${oldArray[@]}")

Это работает легко.

Ответ 8

Я обнаружил, что не так. Мой тест if not installed is two для циклов, которые удаляют лишние символы из имен файлов и выплевывает их, если они существуют на определенном веб-сервере. То, что он не делал, - это удаление конечного дефиса. Итак, когда он протестировал его онлайн для доступности, они были разобраны. Потому что "файл" существует, но "file-" не работает.