Bash заполнить массив в цикле - PullRequest
6 голосов
/ 03 апреля 2012

Как я могу заполнить массив в цикле?Я хотел бы сделать что-то вроде этого:

declare -A results

results["a"]=1
results["b"]=2

while read data; do
results[$data]=1
done

for i in "${!results[@]}"
do
  echo "key  : $i"
  echo "value: ${results[$i]}"
done

Но, похоже, я не могу ничего добавить в массив внутри цикла for.Почему?

Ответы [ 2 ]

15 голосов
/ 03 апреля 2012

То, что у вас есть, должно работать, если у вас есть версия Bash, которая для начала поддерживает ассоциативные массивы.

Если я могу сделать дикое предположение.,,у вас работает что-то вроде этого:

command_that_outputs_keys \
  | while read data; do
        results[$data]=1
    done

?То есть ваша while петля является частью конвейера?Если так, то в этом проблема.Видите ли, каждая команда в конвейере получает копию среды выполнения оболочки.Таким образом, цикл while будет заполнять копию массива results, а когда цикл while завершится, эта копия исчезнет.

Отредактировано, чтобы добавить: Если это является проблемой, то, как Гленн Джекман указывает в комментарии, вы можете исправить это, используя подстановка процесса вместо:

while read data; do
    results[$data]=1
done < <(command_that_outputs_keys)

Таким образом, хотя command_that_outputs_keys получит только копию среды выполнения оболочки (как и раньше), цикл while будет иметь исходную основную среду, поэтому может изменять исходный массив.

1 голос
/ 03 апреля 2012

Это, кажется, работает нормально:

$ cat mkt.sh 
declare -A results

results["a"]=1
results["b"]=2

while read data; do
  results[$data]=1
done << EOF
3
4
5
EOF

for i in "${!results[@]}"
do
  echo "key  : $i"
  echo "value: ${results[$i]}"
done

$ ./mkt.sh 
key  : a
value: 1
key  : b
value: 2
key  : 3
value: 1
key  : 4
value: 1
key  : 5
value: 1
$ 

Ubuntu 11.10 здесь, bash: GNU bash, версия 4.2.10 (1) -релиз (x86_64-pc-linux-gnu).

...