0

I have written the following script:

cat BaseReCall.sh
#!/bin/bash

#### Usage: < input > < ref > < (array of dbsnps) >

input=$1
ref=$2
Pickle=$3

echo "${Pickle[@]}"
### Assign variables
BaseReCall="gatk BaseRecalibrator \\
   -I $input \\
   -R $ref \\
   -O recal_table "
dir=$(dirname $input)
log=${dir}/BaseReCall.out

string=()
## Store array values in string
for i in "${Pickle[@]}";do
  site=$(echo " --known-sites $i")
  string+=$site

done

printf "$BaseReCall${string[@]}\n" #>> $log

The idea is to allow me to enter multiple dbsnp values as Pickle by using an array. If I type into bash the array looks fine.

Pickle=(dbSnp gold_standard_indels)
printf "${Pickle[@]}\n"
dbSnp gold_standard_indels

When I input it into my function however I don't get the two dbsnps. Only the first one.

sh BaseRecall.sh input ref "${Pickle[@]}"
dbSnp
gatk BaseRecalibrator \
   -I input \
   -R ref \
   -O recal_table  --known-sites dbSnp

Just as a sanity check I tried running the loop outside of the script too.

string=()
## Store array values in string
for i in "${Pickle[@]}";do
>  site=$(echo " --known-sites $i")
>  string+=$site

> done
printf "$BaseReCall${string[@]}\n" #>> $log
gatk BaseRecalibrator    -I     -R     -O recal_table --known-sites dbSnp --known-sites gold_standard_indels

and it returned what I wanted all along. Is this happening because it is being inputted as a positional parameter? Is there a way to allow me to input multiple values for this Pickle parameter?

Ctat41
  • 69
  • 6
  • Do not store argument lists as strings. Argument lists should be stored as *arrays* themselves. – Charles Duffy Sep 01 '21 at 17:22
  • 1
    And `printf "${Pickle[@]}\n"` is just wrong. Only the _first_ argument to `printf` is a format string; the subsequent arguments are data to use to fill out that format string. – Charles Duffy Sep 01 '21 at 17:22
  • 1
    `printf '%s\n' "${Pickle[@]}"` is how you print an array one-item-per-line. – Charles Duffy Sep 01 '21 at 17:22
  • 1
    Also, when you expand an array, it creates one argument per entry. So `$3` doesn't contain your whole array, it only contains the first element; the second one goes into `$4`, the third on `$5`, etc. That's not a bug, it's operating-as-designed. You should `shift` the first two items off your argument list so `"$@"` is then your array, if you're expecting an array to be passed in the third position of your script's argument list. – Charles Duffy Sep 01 '21 at 17:23
  • 2
    `declare -p Pickle` is a much better way to see what `Pickle` is -- in this script, it'll make it clear that it's a plain variable rather than an array. – Gordon Davisson Sep 01 '21 at 17:38
  • @CharlesDuffy Could you expand on your first point? Argument lists should be stored as arrays themselves. Is this in reference to BaseReCall variable? – Ctat41 Sep 01 '21 at 17:39

1 Answers1

1

Thanks to some points made in the comments I have fixed the issue I was having. I was misunderstanding arrays and by changing my script from

input=$1
ref=$2
Pickle=$3

to

input=$1
ref=$2
shift 2
Pickle=("$@")

This seems to be working now. A commentator also mentioned using declare to get the status of the array and that also helped a lot. Many thanks.

Ctat41
  • 69
  • 6