Создание ассоциативного массива bash из файла, содержащего разделитель двоеточий - PullRequest
1 голос
/ 08 ноября 2019

У меня есть файл с именем country.txt

cat countries.txt
Germany:berlin
Japan:tokyo
usa:washington
canada:ottawa
uk:london

file='countries.txt'
readarray -t countries < "$file"

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

key  : 0                   
value: Germany:berlin   
key  : 1                   
value: Japan:tokyo   
key  : 2                   
value: usa:washington    
key  : 3                   
value: canada:ottawa  
key  : 4                   
value: uk:london   

моя версия bash - 4.1.2

Результат, который я ожидал увидеть, - это ключ, который представляет собой страны и значенияэто их столицы

После помощи от Inian ниже и использования IFS =: я получаю какой-то странный ответ, подобный этому

declare -A countries
file='countries.txt'

while IFS=: read -r key value; do
    countries["$key"]="$value"
done < "$file"

for cap in "${!countries[@]}"; do
    echo "$cap" "${countries[$cap]}"
done

Japan:tokyo      
uk london        
usa:washington   
canada:ottawa    
Germany berlin   
canada ottawa    
Germany:berlin   
0 countries.txt  
uk:london        
usa washington   
Japan tokyo   

1 Ответ

3 голосов
/ 08 ноября 2019

Известно, что встроенные mapfile / 1002 * в bash создают индексированные массивы только . Поскольку вы не предоставляете никакого ограничителя для разделения содержимого входного файла, команда просто создает одну запись в массиве для каждой из имеющихся строк ввода.

Если вы хотите создать ассоциативный массив сзначения перед : должны использоваться в качестве ключей, вам необходим цикл while, который разбирает каждую строку, разбивая ее на :, и объявляет массив для явного использования в качестве ассоциативного. Обратите внимание, что ассоциативные массивы доступны только в версиях больше 4.

# declares an explicit associative array
declare -A countries

while IFS=: read -r key value; do
    countries["$key"]="$value"
done < "$file"

теперь этот массив может быть зациклен на индексах, а элементы могут быть напечатаны как

for cap in "${!countries[@]}"; do
    printf '%s\n' "$cap" "${countries[$cap]}"
done

См. BashGuide / Arrays для получения более подробной информации о том, как использовать различные типы массивов в bash.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...