50

Is there any way to pipe the output of a command which lists a bunch of numbers (each number in a separate line) and initialize a bash array with those numbers?

Details: This lists 3 changelist numbers which have been submitted in the following date range. The output is then piped to cut to filter it further to get just the changelist numbers.

p4 changes -m 3 -u edk -s submitted @2009/05/01,@now | cut -d ' ' -f 2

E.g. :

422311
543210
444000

How is it possible to store this list in a bash array?

wjandrea
  • 28,235
  • 9
  • 60
  • 81
vivekian2
  • 3,795
  • 9
  • 35
  • 41

3 Answers3

72

You can execute the command under ticks and set the Array like,

ARRAY=(`command`)

Alternatively, you can save the output of the command to a file and cat it similarly,

command > file.txt
ARRAY=(`cat file.txt`)

Or, simply one of the following forms suggested in the comments below,

ARRAY=(`< file.txt`)
ARRAY=($(<file.txt))
nik
  • 13,254
  • 3
  • 41
  • 57
16

If you use bash 4+, it has special command for this: mapfile also known as readarray, so you can fill your array like this:

declare -a a
readarray -t a < <(command)

for more portable version you can use

declare -a a
while read i; do
  a=( "${a[@]}" "$i" )
done < <(command)
Andrey Starodubtsev
  • 5,139
  • 3
  • 32
  • 46
  • 2
    This is my first time seeing `< <(command)`. Can you please help me find more detail on this syntax. I'm interested in knowing why it needs 2 `<` to work. Thanks – bazz Dec 18 '15 at 01:54
  • 3
    First `<` is redirection of input stream, see https://www.gnu.org/software/bash/manual/html_node/Redirections.html#Redirecting-Input for detains. Construction `<(command)` means that output of `command` is piped to named fifo (usually `/dev/fdn`), you can find details on it at https://www.gnu.org/software/bash/manual/html_node/Process-Substitution.html. – Andrey Starodubtsev Dec 18 '15 at 07:09
  • Be warned that `readarray` doesn't support an alternative separator, it always uses newline. – ivan_pozdeev May 14 '16 at 18:48
  • 3
    `a[${#a[*]}]=value` or `a+=(value)` is a better syntax to append to an array. – ivan_pozdeev May 14 '16 at 18:52
  • 1
    Re @ivan_pozdeev `readarray`/`mapfile` apparently does support defining alternative delimiters. The [docs](https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html#index-mapfile) specify `-d delim`: "The first character of delim is used to terminate each input line, rather than newline." – Allan Lewis Dec 08 '17 at 12:24
  • @AllanLewis `-d` for `readarray` [is new in `bash 4.4`](http://git.savannah.gnu.org/cgit/bash.git/diff/NEWS?id=a0c0a00fc419b7bc08202a79134fcd5bc0427071). – ivan_pozdeev Dec 08 '17 at 19:40
3

Quite similar to #4 but looks a bit better for me. :)

declare -a a
readarray -t a <<< $(command)
Maciej Wawrzyńczuk
  • 860
  • 1
  • 8
  • 19
  • Interesting alternative. However the methods differ in case of an empty output from the command, the here-string method gives an array having one empty item, whereas the names pipe method gives an empty array. – luciole75w Nov 19 '19 at 02:47