简体   繁体   中英

Creating 2D Array from command output in Bash

I am trying to set the rows and columns from a command into a multi-dimensional array to compare columns in each row. The command I am using is: (semanage login -l | more) The output is:

Login Name           SELinux User         MLS/MCS Range        Service

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

My current code only sets each row to an index of a 1D array, how do I either separate each column (ex: Login Name, SELinux User, etc) from the command output into their own arrays, or create a 2D array? Here is my current code:

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

There is no support for multidimensional arrays in bash -- but you don't need them for this use case, where the number of columns is fixed and known.

As an example that reads each column into a different associative array, consider:

#!/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

...which emits as output the following array definitions:

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]="*" )

One way to represent a multi-dimension array in bash 4 or later would be to use an associative array.

You would produce a string which is the concatenation of all the indices you want, and use that as the associative index.

This is only really useful if all you want to do is loop through the elements, and if you want the schema to report back the dimensions then you would need to stash those values as extra members.

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

If you like @Charles's idea of using the login name as the first index you can, though you would also need to keep a list of the login names. With charles' model, you can ask any of the lists for their index values. You can use the column names as the second index. You would then need to be careful that the name separator , is not used as a name, though, or use a different separator character.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM