Создание 2D массива из вывода команды в Bash

Я пытаюсь установить строки и столбцы из команды в многомерный массив для сравнения столбцов в каждой строке. Я использую команду: (semanage login -l | more) Вывод:

Login Name           SELinux User         MLS/MCS Range        Service

__default__          user_u               s0                   *
user1                user_u               s0                   *
root                 unconfined_u         s0-s0:c0.c1023       *

Мой текущий код только устанавливает в каждой строке индекс одномерного массива. Как мне отделить каждый столбец (например, Имя для входа, Пользователь SELinux и т. Д.) От вывода команды в их собственные массивы или создать двумерный массив? Вот мой текущий код:

my_array=()
while IFS= read -ra line; do
    my_array+=("${line}")
    echo "${line}"
done < <(semanage login -l | more)

Всего 2 ответа


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

В качестве примера, который читает каждый столбец в отдельный ассоциативный массив, рассмотрим:

#!/usr/bin/env bash

get_data() {
  # in a real version this would run semanage login -l
  cat <<'EOF'
Login Name           SELinux User         MLS/MCS Range        Service

__default__          user_u               s0                   *
user1                user_u               s0                   *
root                 unconfined_u         s0-s0:c0.c1023       *
EOF
}

declare -A selinux_users=() ranges=() services=()
{
  read _; read _ # discard header and leading blank line
  while read -r login_name selinux_user range service; do
    selinux_users[$login_name]=$selinux_user
    ranges[$login_name]=$range
    services[$login_name]=$service
  done
} < <(get_data)

# for debugging, print the result of the operation
declare -p selinux_users ranges services

... который выводит следующие определения массива:

declare -A selinux_users=([user1]="user_u" [__default__]="user_u" [root]="unconfined_u" )
declare -A ranges=([user1]="s0" [__default__]="s0" [root]="s0-s0:c0.c1023" )
declare -A services=([user1]="*" [__default__]="*" [root]="*" )

Одним из способов представления многомерного массива в bash 4 или более поздней версии является использование ассоциативного массива.

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

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

declare -A myArray
myArray['!dims!']=2
myArray['!dim!0']=20
myArray['!dim!1']=z4

for x in {0..19} ;  do for y in {0..3} ; do 
   myArray["$x,$y"]=$value
done;done

Если вам нравится идея @ Charles об использовании имени для входа в качестве первого индекса, вы можете также сохранить список имен для входа. С помощью модели Чарльза вы можете запросить любой из списков для их значений индекса. Вы можете использовать имена столбцов в качестве второго индекса. Тогда вам нужно быть осторожным, чтобы разделитель имен не использовался как имя, или использовал другой символ разделителя.


Есть идеи?

10000