I have a file called "threewords". It contains the information:

\#gray speedy bee

gr-A | sp-E-d-E | b-E

\#gray greedy pea

gr-A | gr-E-d-E | p-E

When I run the command:

cat threewords | grep ^# | cut -c2-

The command pulls the two lines beginning with #. It then removes the # and returns this as output:

gray speedy bee

gray greedy pea

When I run my command:

array=($(cat threewords | grep ^# | cut -c2-))

It creates the array but it separates all the words into separate array positions like this:

array[0] = gray,
array[1] = speedy,
array[2] = bee,
array[3] = gray,
array[4] = greedy,
array[5] = pea

I can figure out the code to make it put the output of each line into an array like so:

array[0] = gray speedy bee, 
array[1] = gray greedy pea
  • 1
    this is a terrible idea. – mikeserv Dec 14 '14 at 1:18

The splitting is done with IFS as the delimiter (which contains a space, newline and tab by default). Set the IFS to only the newline:

$ IFS=$'\n' a=($(printf "1 2\n2 3\n"))
$ echo ${a[0]}
1 2
$ echo ${a[1]}
2 3

This will change IFS for the shell, so best save it before and restore it:

IFS=$'\n' array=($(grep '^#' threewords | cut -c2-))

And there's absolutely no reason to do:

cat threewords | grep '^#'

grep is perfectly capable of reading files:

grep '^#' threewords

As Stephane notes, when subjecting the output of a command to further shell expansion, one should disable globbing using set -f:

$ help set 
      -f  Disable file name generation (globbing).


$ cd /; a=( $(printf "*\n") )
$ echo ${a[@]}
bin boot cdrom dev etc home ...

If you have bash 4

mapfile -t array < <(grep ^# threewords | cut -c2-)

Will populate array, one line per element

printf "%s\n" "${array[@]}"
gray speedy bee
gray greedy pea

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.