Home > other >  Reading output into array with bash and readarray
Reading output into array with bash and readarray

Time:11-02

I am trying to follow a tutorial in order to read df -h into an array.

this is the primary information command:
df -h --output='itotal','iavail','target'

the output looks as follows:
enter image description here

the code in order to transfer to array looks as follows:

#!/bin/bash
df_info=$(df -h --output='itotal','iavail','target')
readarray -t drives <<< "$df_info"
declare -p drives

result (reformatted for human readability):

drives=(
  [0]="Inodes IFree Mounted on"
  [1]="  2.0M  2.0M /dev"
  [2]="  2.0M  2.0M /run"
  [3]="   30M   30M /"
  [4]="  2.0M  2.0M /dev/shm"
  [5]="  2.0M  2.0M /run/lock"
  [6]="  2.0M  2.0M /sys/fs/cgroup"
  [7]="   11K     0 /snap/core18/2128"
  [8]="   12K     0 /snap/core20/1081"
  [9]="     0     0 /boot/efi"
  [10]="   474     0 /snap/snapd/13270"
  [11]="   11K     0 /snap/core18/2246"
  [12]="   479     0 /snap/snapd/13640"
  [13]="   12K     0 /snap/core20/1169"
  [14]="   796     0 /snap/lxd/21545"
  [15]="  1.6K     0 /snap/lxd/21029"
  [16]="   30M   30M /mnt/tmp_plot2"
  [17]="   30M   30M /mnt/tmp_plot1"
  [18]="  233M  233M /mnt/plotfield1"
  [19]="  233M  233M /mnt/plotfield2"
  [20]="  233M  233M /mnt/plotfield3"
  [21]="  233M  233M /mnt/plotfield5"
  [22]="  233M  233M /mnt/plotfield_ext"
  [23]="  175M  175M /mnt/plotfield4"
  [24]="  2.0M  2.0M /run/user/1000"$
)

so far, the output looks good. In the next step, I want to split into the fields 'Inodes', 'IFree' and 'Mounted On'

I implemented the following code:

for val in ${drives[@]}; do
  printf "printing line: "
  echo $val
  readarray -t fields <<< "$val"
  declare -p fields
  printf "printing fields: "
  echo $fields
done

the expected result on printf "printing line: " && echo $val
would be something like: " 2.0M 2.0M /dev"

instead, the loop runs not over each line once but over each word in df -h:

printing line: Inodes
declare -a fields=([0]="Inodes")
printing fields: Inodes
printing line: IFree
declare -a fields=([0]="IFree")
printing fields: IFree
printing line: Mounted
declare -a fields=([0]="Mounted")
printing fields: Mounted
printing line: on
declare -a fields=([0]="on")
printing fields: on
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /dev
declare -a fields=([0]="/dev")
printing fields: /dev
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /run
declare -a fields=([0]="/run")
printing fields: /run
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: /
declare -a fields=([0]="/")
printing fields: /
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /dev/shm
declare -a fields=([0]="/dev/shm")
printing fields: /dev/shm
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /run/lock
declare -a fields=([0]="/run/lock")
printing fields: /run/lock
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /sys/fs/cgroup
declare -a fields=([0]="/sys/fs/cgroup")
printing fields: /sys/fs/cgroup
printing line: 11K
declare -a fields=([0]="11K")
printing fields: 11K
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/core18/2128
declare -a fields=([0]="/snap/core18/2128")
printing fields: /snap/core18/2128
printing line: 12K
declare -a fields=([0]="12K")
printing fields: 12K
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/core20/1081
declare -a fields=([0]="/snap/core20/1081")
printing fields: /snap/core20/1081
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /boot/efi
declare -a fields=([0]="/boot/efi")
printing fields: /boot/efi
printing line: 474
declare -a fields=([0]="474")
printing fields: 474
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/snapd/13270
declare -a fields=([0]="/snap/snapd/13270")
printing fields: /snap/snapd/13270
printing line: 11K
declare -a fields=([0]="11K")
printing fields: 11K
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/core18/2246
declare -a fields=([0]="/snap/core18/2246")
printing fields: /snap/core18/2246
printing line: 479
declare -a fields=([0]="479")
printing fields: 479
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/snapd/13640
declare -a fields=([0]="/snap/snapd/13640")
printing fields: /snap/snapd/13640
printing line: 12K
declare -a fields=([0]="12K")
printing fields: 12K
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/core20/1169
declare -a fields=([0]="/snap/core20/1169")
printing fields: /snap/core20/1169
printing line: 796
declare -a fields=([0]="796")
printing fields: 796
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/lxd/21545
declare -a fields=([0]="/snap/lxd/21545")
printing fields: /snap/lxd/21545
printing line: 1.6K
declare -a fields=([0]="1.6K")
printing fields: 1.6K
printing line: 0
declare -a fields=([0]="0")
printing fields: 0
printing line: /snap/lxd/21029
declare -a fields=([0]="/snap/lxd/21029")
printing fields: /snap/lxd/21029
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: /mnt/tmp_plot2
declare -a fields=([0]="/mnt/tmp_plot2")
printing fields: /mnt/tmp_plot2
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: 30M
declare -a fields=([0]="30M")
printing fields: 30M
printing line: /mnt/tmp_plot1
declare -a fields=([0]="/mnt/tmp_plot1")
printing fields: /mnt/tmp_plot1
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: /mnt/plotfield1
declare -a fields=([0]="/mnt/plotfield1")
printing fields: /mnt/plotfield1
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: /mnt/plotfield2
declare -a fields=([0]="/mnt/plotfield2")
printing fields: /mnt/plotfield2
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: /mnt/plotfield3
declare -a fields=([0]="/mnt/plotfield3")
printing fields: /mnt/plotfield3
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: /mnt/plotfield5
declare -a fields=([0]="/mnt/plotfield5")
printing fields: /mnt/plotfield5
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: 233M
declare -a fields=([0]="233M")
printing fields: 233M
printing line: /mnt/plotfield_ext
declare -a fields=([0]="/mnt/plotfield_ext")
printing fields: /mnt/plotfield_ext
printing line: 175M
declare -a fields=([0]="175M")
printing fields: 175M
printing line: 175M
declare -a fields=([0]="175M")
printing fields: 175M
printing line: /mnt/plotfield4
declare -a fields=([0]="/mnt/plotfield4")
printing fields: /mnt/plotfield4
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: 2.0M
declare -a fields=([0]="2.0M")
printing fields: 2.0M
printing line: /run/user/1000
declare -a fields=([0]="/run/user/1000")
printing fields: /run/user/1000

CodePudding user response:

As Barmar's pointed out wrap ${drives} in double quotes so the whole 'line' is read into variable val otherwise the line is split on white space and processed one 'word' at a time.

Other items you'll run into once you get val populated correctly:

  • readarray is used to read an entire line (from a file) into an array
  • I'm assuming what you want to do is read each 'word' in val into separate array elements in which case ...
  • try read -a to split val into individual array elements
  • since fields is an array, and assuming the intent is to display all contents of fields on a single line ...
  • you want to replace echo $fields with echo "${fields[@]}"
  • as is echo $fields prints the contents of fields[0]

Pulling all of this together:

for val in "${drives[@]}"; do
  printf "printing line: "
  echo $val
  read -r -a fields <<< "$val"
# fields=( ${val} )                  # alternative to 'read -a'; no double quotes since we *want* word splitting
  declare -p fields
  printf "printing fields: "
  echo "${fields[@]}"
done

Which generates:

printing line: Inodes IFree Mounted on
declare -a fields=([0]="Inodes" [1]="IFree" [2]="Mounted" [3]="on")
printing fields: Inodes IFree Mounted on
printing line: 2.0M 2.0M /dev
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/dev")
printing fields: 2.0M 2.0M /dev
printing line: 2.0M 2.0M /run
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/run")
printing fields: 2.0M 2.0M /run
printing line: 30M 30M /
declare -a fields=([0]="30M" [1]="30M" [2]="/")
printing fields: 30M 30M /
printing line: 2.0M 2.0M /dev/shm
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/dev/shm")
printing fields: 2.0M 2.0M /dev/shm
printing line: 2.0M 2.0M /run/lock
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/run/lock")
printing fields: 2.0M 2.0M /run/lock
printing line: 2.0M 2.0M /sys/fs/cgroup
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/sys/fs/cgroup")
printing fields: 2.0M 2.0M /sys/fs/cgroup
printing line: 11K 0 /snap/core18/2128
declare -a fields=([0]="11K" [1]="0" [2]="/snap/core18/2128")
printing fields: 11K 0 /snap/core18/2128
printing line: 12K 0 /snap/core20/1081
declare -a fields=([0]="12K" [1]="0" [2]="/snap/core20/1081")
printing fields: 12K 0 /snap/core20/1081
printing line: 0 0 /boot/efi
declare -a fields=([0]="0" [1]="0" [2]="/boot/efi")
printing fields: 0 0 /boot/efi
printing line: 474 0 /snap/snapd/13270
declare -a fields=([0]="474" [1]="0" [2]="/snap/snapd/13270")
printing fields: 474 0 /snap/snapd/13270
printing line: 11K 0 /snap/core18/2246
declare -a fields=([0]="11K" [1]="0" [2]="/snap/core18/2246")
printing fields: 11K 0 /snap/core18/2246
printing line: 479 0 /snap/snapd/13640
declare -a fields=([0]="479" [1]="0" [2]="/snap/snapd/13640")
printing fields: 479 0 /snap/snapd/13640
printing line: 12K 0 /snap/core20/1169
declare -a fields=([0]="12K" [1]="0" [2]="/snap/core20/1169")
printing fields: 12K 0 /snap/core20/1169
printing line: 796 0 /snap/lxd/21545
declare -a fields=([0]="796" [1]="0" [2]="/snap/lxd/21545")
printing fields: 796 0 /snap/lxd/21545
printing line: 1.6K 0 /snap/lxd/21029
declare -a fields=([0]="1.6K" [1]="0" [2]="/snap/lxd/21029")
printing fields: 1.6K 0 /snap/lxd/21029
printing line: 30M 30M /mnt/tmp_plot2
declare -a fields=([0]="30M" [1]="30M" [2]="/mnt/tmp_plot2")
printing fields: 30M 30M /mnt/tmp_plot2
printing line: 30M 30M /mnt/tmp_plot1
declare -a fields=([0]="30M" [1]="30M" [2]="/mnt/tmp_plot1")
printing fields: 30M 30M /mnt/tmp_plot1
printing line: 233M 233M /mnt/plotfield1
declare -a fields=([0]="233M" [1]="233M" [2]="/mnt/plotfield1")
printing fields: 233M 233M /mnt/plotfield1
printing line: 233M 233M /mnt/plotfield2
declare -a fields=([0]="233M" [1]="233M" [2]="/mnt/plotfield2")
printing fields: 233M 233M /mnt/plotfield2
printing line: 233M 233M /mnt/plotfield3
declare -a fields=([0]="233M" [1]="233M" [2]="/mnt/plotfield3")
printing fields: 233M 233M /mnt/plotfield3
printing line: 233M 233M /mnt/plotfield5
declare -a fields=([0]="233M" [1]="233M" [2]="/mnt/plotfield5")
printing fields: 233M 233M /mnt/plotfield5
printing line: 233M 233M /mnt/plotfield_ext
declare -a fields=([0]="233M" [1]="233M" [2]="/mnt/plotfield_ext")
printing fields: 233M 233M /mnt/plotfield_ext
printing line: 175M 175M /mnt/plotfield4
declare -a fields=([0]="175M" [1]="175M" [2]="/mnt/plotfield4")
printing fields: 175M 175M /mnt/plotfield4
printing line: 2.0M 2.0M /run/user/1000$
declare -a fields=([0]="2.0M" [1]="2.0M" [2]="/run/user/1000\$")
printing fields: 2.0M 2.0M /run/user/1000$
  • Related