1

Hi I have created two arrays:

$ echo "${prot}"
abc
def
ghi

$ echo "${pos}"
123
456
789

where element n in prot refers to element n in pos. so I want to print the corresponding elements on one line, with one new line per pair.

I am trying to do this with a nested loop, where I split the respective arrays into elements via a newline:

for i in "${!prot[@]}";  do
    for j in "${!pos[@]}";  do
        IFS=$'\n' read -a arr1 <<<"$i"
        IFS=$'\n' read -a arr2 <<<"$j"
        echo $i $j  
    done
done

but this only gives me the last pair. it's one line which is great, but it's not printing them all. what am I doing wrong?

Expected output:

$
    abc 123
    def 456
    ghi 789

I created the arrays in the first place by doing

    for i in *.fasta; do
    IFS=_-. read -ra arr <<<"$i"
    tmp=$(printf "${arr[*]: 0: 1} ${arr[*]: 1: 1} ${arr[*]: -2: 1}")
    fa+="$tmp\n"
    done

   for i in "${fa[@]}"; do
   prot=$(echo -e "$i" | cut -d\  -f 1)
   pos=$(echo -e "$i" | cut -d\ -f 2) 
   done
brucezepplin
  • 9,202
  • 26
  • 76
  • 129
  • 1
    `${prot}` is just the same as `$prot`. `${prot[@]}` is the array. – choroba Mar 31 '15 at 14:35
  • 1
    More specifically, `prot` is *not* an array, but a string with embedded newlines. – chepner Mar 31 '15 at 14:56
  • 1
    confirm that `prot` and `pos` are **arrays** and not simple variables that contain 3-words with embedded **newlines**. – David C. Rankin Mar 31 '15 at 14:57
  • If `echo "${prot}"` spits out all three of those lines then you don't have an array you have a string. – Etan Reisner Mar 31 '15 at 14:58
  • I also have doubts that `fa` is an array; how does *that* get created? – chepner Mar 31 '15 at 15:00
  • @David C. Rankin - you are right, I thought they were arrays but they are not. the last chunk of code in my questions shows how I "generate" what I thought were arrays – brucezepplin Mar 31 '15 at 15:00
  • @chepner - have added how I create `fa` in last code chunk of question – brucezepplin Mar 31 '15 at 15:02
  • 1
    Happens to all of us... Once they are in arrays, a single loop is all that is needed. You can use the `seq` approach to iterate, or a c-style loop `for((i=0;i<${#array[@];i++)); do` to output both elements side by side. – David C. Rankin Mar 31 '15 at 15:02

2 Answers2

2

First you have to split strings into proper bash arrays:

readarray -t prot_array <<< "$prot"
readarray -t pos_array <<< "$pos"

Then, I would try something like:

for ((i=0; i<${#prot_array[@]}; i++)); do
    echo "${prot_array[i]} ${pos_array[i]}";
done

It's simple solution without nested loops. ${#prot[@]} is the size of the array. The loop displays corresponding elements of both arrays.

tmp
  • 1,079
  • 9
  • 16
  • thank you. it does print out all elements, however it doesn't appear to split the input by newline, hence all of `${prot[i]}` gets printed first on x newlines, followed by `${pos[i]}`. the inputs need to be read into an array that splits elements by newline. I shall add how I created the initial arrays in question. – brucezepplin Mar 31 '15 at 14:46
  • have added expected output and how i created initial arrays – brucezepplin Mar 31 '15 at 14:51
  • @brucezepplin take a look at: [bash split string into array](http://stackoverflow.com/questions/10586153/bash-split-string-into-array) – tmp Mar 31 '15 at 14:51
  • Use a C-style for loop (`for ((i=0; i<${#prot[@]}; i++))`) instead of `seq`. – chepner Mar 31 '15 at 14:55
  • @tmp that post is helpful, however I still cannot output `prot[1]` and `pos[1]` on same line. following the method on the link i output all elements of `prot[@]` with each element on a newline, followed by the same for `$pos[@]` – brucezepplin Mar 31 '15 at 14:59
  • I think the problem is that they aren;t arrays, but rather lines of strings as @David has pointed out. – brucezepplin Mar 31 '15 at 15:01
  • @brucezepplin - code for splitting strings into arrays added – tmp Mar 31 '15 at 15:19
1

Another way that works even when dealing with arrays of differing length is simply to use a while loop with a counter variable to output the arrays side-by-side so long as both arrays have values:

#!/bin/bash

a1=( 1 2 3 4 5 )
a2=( a b c d e f g )

declare -i i=0

while [ "${a1[i]}" -a "${a2[i]}" ]; do

    printf " %s  %s\n" "${a1[i]}" "${a2[i]}"
    ((i++))

done

exit 0

Output

$ bash arrays_out.sh
 1  a
 2  b
 3  c
 4  d
 5  e
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85