0

Hello I try to split awk to a array. I have this script:

#!/bin/bash

vms_disks=( "${vms_disks[@]}" "$(virsh domblklist $vm --details | awk '/disk/{print $4}')" )
for disk in "${vms_disks[@]}"; do
  echo "upload $disk"
done

This script should get the drives of a virtual maschine "$vm" in a array "${vms_disks[@]}". But this script fill the array "${vms_disks[@]}" with only one key. the output of echo should be:

upload disk1.raw
upload disk2.raw
...

(upload for each Disk)

but I get:

upload disk1.raw disk2.raw ...

(only one Upload for all Disks together)

How to get the array-keys from "$(virsh domblklist $vm --details | awk '/disk/{print $4}')"

how to do that?

fteinz
  • 1,085
  • 5
  • 15
  • 30
  • Why not start with `vms_disks=( "$(printf 'hello\nworld\n')" )` or similar and try to get that working first before adding all the other complexity? – Ed Morton Nov 06 '19 at 13:59

2 Answers2

1

Could you please try following, haven't tested it since lack of samples.

mapfile -t myarr < <(virsh domblklist $vm --details | awk '/disk/{print $4}')
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
1

When you put double quotes around:

"$(virsh domblklist $vm --details | awk '/disk/{print $4}')"

You are preventing word splitting from occurring, which means that the contents of your array are a maximum of two elements (words).

If the array vms_disks is initially empty, then "${vms_disks[@]}" expands to nothing, so your array only has one element.

Assuming that the output of "$(virsh domblklist $vm --details | awk '/disk/{print $4}' only has spaces between the elements, then I think you can just remove the quotes and allow word splitting to happen:

vms_disks=( "${vms_disks[@]}" $(virsh domblklist "$vm" --details | awk '/disk/{print $4}') )

Don't forget that quotes inside the command substitution (e.g. around $vm) are still important!

Since you're already making the assumption that virsh domblklist $vm --details output only contains newlines between records, a slightly more robust way to do the same thing would be to use a loop to build the array:

vms_disks=()
while IFS= read -r disk; do
  vms_disks+=( "$disk" )
done < <(virsh domblklist "$vm" --details | awk '/disk/{print $4}')

A slightly shorter form to do the same thing would be to use mapfile/readarray:

virsh domblklist "$vm" --details | awk '/disk/{print $4}' | 
  mapfile -O ${#vms_disks[@]} -t vms_disks

I'm using -O ${#vms_disks[@]} to start writing to the end of the array vms_disks, in case it already exists and contains elements (this matches your attempt in the question).

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141