0

Im trying to make this pipeline more flexible. So say I want to be able to easily switch the number of times a for loop is run, based on whether or not I want to analyse all my data.

#!/bin/bash
#AllCohorts='Yes'
AllCohorts='NotAll'
groups=$(wc -l Groups | awk '{print $1}' ) 

if [[ $AllCohorts == *Yes* ]]
then
    for pheno in `seq 1 $groups`; 
    do
    out=$(sed -n "$pheno"'p' Groups) 
    whichPheno=$pheno
elif [[ $AllCohorts == *Not* ]]
then
    nbGroups=$(wc -l TestingGroups | awk '{print$1}')
    for pheno in `seq 1 $nbGroups`; 
    do
    out=$(sed -n "$pheno"'p' Groups) 
    hit=$(grep -n $out TestingGroups) 
    whichPheno=${hit%:*} 
fi

This gives an error:

$ sh run_gene_tests.sh
run_gene_tests.sh: line 29: syntax error near unexpected token `elif'
run_gene_tests.sh: line 29: `elif [[ $AllCohorts == *Not* ]]'

What Im wondering is, does the code you have in between the if and elif/fi have to be self contained? or can you do what im trying here and just have the for loop starting in one of two ways based on AllCohorts

3
  • You are missing the done from your for loop. Commented Oct 30, 2014 at 13:56
  • You're missing a done Commented Oct 30, 2014 at 13:56
  • 1
    By the way, if you just want the number of lines in a file you can do wc -l < filename. This passes the contents of the file on standard input so you don't need to then use another tool to remove the filename from the output. Commented Oct 30, 2014 at 13:57

2 Answers 2

1

You're missing done at the end of the for loops

if [[ $AllCohorts == *Yes* ]]
then
    for pheno in `seq 1 $groups`; 
    do
        out=$(sed -n "$pheno"'p' Groups) 
        whichPheno=$pheno
    done
elif [[ $AllCohorts == *Not* ]]
then
    nbGroups=$(wc -l TestingGroups | awk '{print$1}')
    for pheno in `seq 1 $nbGroups`; 
    do
        out=$(sed -n "$pheno"'p' Groups) 
        hit=$(grep -n $out TestingGroups) 
        whichPheno=${hit%:*} 
    done
fi
Sign up to request clarification or add additional context in comments.

5 Comments

Am I? Theres a lot more code after this bit to run, that Ive left outside of this IF block because its the same for both conditions. I have the done after this. The two "For"s here share a done
You can't share a done between two fors. They have to be nested properly.
But only one of the fors gets used because of the if. I still cant do it?
No, you can't. The body of an if or elif must be self-contained. Look at the syntax in the bash manual.
@pepsimax The thing to realize is that done is not a separate command that jumps back to the previous loop. for ..; do ..; done is a single compound command, and has to be specified completely. That's why you can't share a done like you would share a rm for cleanup.
0

Some enhancements using less external tools:

readarray grouptab < Groups || exit 1

if [[ "$AllCohorts" == *Yes* ]]; then
    for ((pheno=1;pheno <= groups; pheno++)); do     # use for loop
        out=${grouptab[pheno+1]}                     # avoid sed
        whichPheno=$pheno
    done
elif [[ "$AllCohorts" == *Not* ]]; then
    nbGroups=$(wc -l < TestingGroups)                # avoid awk using <
    for ((pheno=1;pheno <= nbGroups; pheno++)); do   # use for loop
        out=${grouptab[pheno+1]}                     # avoid sed
        hit=$(grep -n "$out" TestingGroups) 
        whichPheno=${hit%:*} 
    done
fi

Comments

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.