2

I have either a file (or the output of a command) that has block of lines separated by the empty line - like below:

1
2
3

4
5
6

cannot figure out how to populate bash (4.4.12) array with "block" of lines for each array cell, e.g.

arr[0]='
1
2
3'

array[1]='
4
5
6'

Looked around for similar threads with readarray, mapfile, played with IFS/read and other alternatives, but cannot figure out how to do the "blocks" of lines, not simply one-line-at-the time. What's the magic combo?

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
vgersh99
  • 877
  • 1
  • 5
  • 9
  • you could replace every double newline \n\n with some other character (like \r) and use that as IFS – alecxs Aug 19 '20 at 21:38
  • 5
    Don't tag `sh` for questions about features -- like arrays -- that aren't in the POSIX sh standard. You need to be using bash, ksh, zsh, or another extended shell for those (and obvs., details can vary depending on exactly which shell is in use). – Charles Duffy Aug 19 '20 at 21:49
  • @CharlesDuffy understood! – vgersh99 Aug 19 '20 at 21:59

2 Answers2

7

With bash:

declare -i c=0                      # set integer attribute

while IFS= read -r line; do
  [[ -z $line ]] && c+=1
  arr[$c]+="$line"$'\n'
done < file

declare -p arr                      # output array

Output:

declare -a arr=([0]=$'1\n2\n3\n' [1]=$'\n4\n5\n6\n')
Cyrus
  • 84,225
  • 14
  • 89
  • 153
  • 3
    Nice; that's significantly cleaner than the approach I've historically taken, of appending items to the array only after accumulation is complete. – Charles Duffy Aug 19 '20 at 21:48
1

Here's another approach on a similar SO thread:

while IFS= read -r -d '' rec
do
  arr2+=("${rec}")
done < <(awk '1' RS= ORS='\x0' file)

declare -p arr2
vgersh99
  • 877
  • 1
  • 5
  • 9