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
8
  • 1
    ${prot} is just the same as $prot. ${prot[@]} is the array. Commented Mar 31, 2015 at 14:35
  • 1
    More specifically, prot is not an array, but a string with embedded newlines. Commented Mar 31, 2015 at 14:56
  • 1
    confirm that prot and pos are arrays and not simple variables that contain 3-words with embedded newlines. Commented Mar 31, 2015 at 14:57
  • If echo "${prot}" spits out all three of those lines then you don't have an array you have a string. Commented Mar 31, 2015 at 14:58
  • 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. Commented Mar 31, 2015 at 15:02

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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.
have added expected output and how i created initial arrays
@brucezepplin take a look at: bash split string into array
Use a C-style for loop (for ((i=0; i<${#prot[@]}; i++))) instead of seq.
@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[@]
|
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

1 Comment

It's very neat!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.