Score:0

Syntax error while using End of Message (EOM) inside a while loop in ubuntu shell script

in flag

I have a code containing a command where the user is prompted to select an option from those shown in the menu. This needs to be repeatedly executed for several times, hence I have used the while loop. Now, I have used EOM (End of message) method to give input when prompted. While using I have noticed that this method yeilds the follwoing error when executed. I have narrowed down the bug to this part of the code (line 80 to 83) and am not able to get pass this.

Please help me resolve this.

The lines where the error is ocuring:

TEMP="q"
gmx_mpi make_ndx -f pull_sim.gro -o index.ndx <<EOM
$TEMP
EOM

Error:

./Run_Pull_Code.sh: 105: Syntax error: end of file unexpected (expecting "done")

Kindly find the full following code (refer to lines 80 to 83 here):

#!/bin/sh
# The above comment sets the sh file to execute as an interpreter (Line by line)

# Finding the current working directory
BASEDIR=$(pwd)
echo "I am currently in the following directory:"
echo "$BASEDIR"
echo " "


##########################################################################################
# Setting the pulling code positions and decrements (All in nm)
##########################################################################################
DECREMENT=0.5      #Steps in nm
RANGE=1            #From the highest to the lowest position
MID_POS=9.327      #Observing the highest water molecule (O atom) of the water surface
INIT_POS=$( echo "$MID_POS + $RANGE" | bc -l)  # Initial position
LAST_POS=$( echo "$MID_POS - $RANGE" | bc -l)  # Final position
CURR_POS=$INIT_POS # Assigning the Initial position as the current position


LOOP_CNT=0
while [ 1 -eq "$(echo "${LAST_POS} <= ${CURR_POS}" | bc)" ]
do 
    # increment the value
    LOOP_CNT=$( echo "$LOOP_CNT + 1" | bc -l)
    DISTANCE=$CURR_POS

    # Setting the loop number (X) as the pull code number for simulation (X)
    SIM_CNT=$LOOP_CNT

    # Making the directories (1) X_Pull (2) X_Pull/Making
    DIR_NAME_MAIN=$SIM_CNT"_Pull"
    mkdir $DIR_NAME_MAIN
    DIR_NAME_MAKING=$SIM_CNT"_Pull/Making"
    mkdir $DIR_NAME_MAKING
    
    echo " "
    echo "I have made the directories."
    echo " "

    # Copying the files from prerequisites folder to the newly created folder
    cp Prerequisites/Avo_decanol.pdb Prerequisites/water_box.pdb $DIR_NAME_MAKING
    cp Prerequisites/simulation_file.mdp Prerequisites/topol.top $DIR_NAME_MAIN
    
    ##########################################################################################
    # Making the simulation box "pull_sim.gro"
    ##########################################################################################
    cd $DIR_NAME_MAKING
    #(1) Fix the distance of the decanol from the water surface and make the only decanol box with the same dimension as that of the water box
    DISTANCE=9.5 
    gmx_mpi editconf -f Avo_decanol.pdb -o Dec_box.pdb -center 2.5 2.5 $DISTANCE -box 5 5 12
    #(2) CREATING CONSTANT HEADER AND ENDER cat files in PDB format
    #The first 4 lines of any PDB file contains the information of the box size and the name, etc.
    #Just copy the four lines into a separate HEADER PDB file by the following command.
    sed -n '1,4p' Dec_box.pdb > HEADER.pdb
    #The last 2 lines are also common to all PDB files, hence copy these to a ENDER PDB file by the following command.
    sed -n '38,39p' Dec_box.pdb > ENDER.pdb
    #(3) Separate the decanol atom properties from its PDB file (line 5 to 37) by the follwing command
    sed -n '5,37p' Dec_box.pdb > file_1.pdb
    #(4) Separate the water atom properties from its PDB file (line 5 to 15004) by the follwing command
    sed -n '5,15004p' water_box.pdb > file_2.pdb
    #(5) Now connect all the above files with the water surface PDB file in the following sequence:
    cat HEADER.pdb file_1.pdb file_2.pdb ENDER.pdb > pull_sim.pdb
    #(6) Rearrange all the number of atoms in the pull_sim.pdb and convert it into a GRO file, pull_sim.gro file.
    gmx_mpi editconf -f pull_sim.pdb -o pull_sim.gro -center 2.5 2.5 6.0 -box 5.0 5.0 12.0 -resnr 1

    # Copying the recently made pull_sim.gro file from making folder to the previous folder
    cd ../
    cp Making/pull_sim.gro ./
        
    echo " "
    echo "The pull box has been created."
    echo " "
    
    ##########################################################################################
    # Starting the simulation
    ##########################################################################################
    # (1) Making index file
    TEMP="q"
    gmx_mpi make_ndx -f pull_sim.gro -o index.ndx <<EOM
    $TEMP
    EOM
    # (2) Creating tpr file from grompp module
    gmx_mpi grompp -f simulation_file.mdp -p topol.top -c pull_sim.gro -n index.ndx -maxwarn 0 -o nvt.tpr
    # Clearing all the contents
    clear
    echo " "
    echo "#####################*********** Pull Simulation: $LOOP_CNT ***********#####################"
    echo " "
    # (3) mdrun
    gmx_mpi mdrun -v -deffnm nvt -nb gpu -pme gpu -pmefft gpu -bonded gpu
        
    # Moving back to the main folder
    cd ../
    
    # Decrementing the distance for the next loop
    CURR_POS=$( echo "$CURR_POS - $DECREMENT" | bc -l)
done
    
#clear
echo " "
echo "Complete"
echo " "
terdon avatar
cn flag
What is the error? And what input does this `gmx_mpi make_ndx` command expect? How would you run it if you were not using heredocs (EOM)? Would you pass it a file? A string?
terdon avatar
cn flag
And some general comments: i) avoid using CAPS for variable names in shell scripts. By convention, global environment variables are capitalized so having your own variables in caps can lead to variable name collisions which can be very hard to debug. It is generally good practice to avoid caps in shell scripts. ii) ***always double quote your variables***. See [Security implications of forgetting to quote a variable in bash/POSIX shells](https://unix.stackexchange.com/q/171346). iii) you can increment a variable natively in the shell, no need for `bc`: `let LOOP_CNT++` or `((LOOP_CNT++))`.
in flag
Thank you for your advice. I have now edited and mentioned the error. Please have a look.
Score:2
cn flag

Heredocs cannot be indented like the rest of the script (unless you use -EOM but then you can only indent with tabs). After all, the purpose of the heredoc is to allow you to write something that will appear as is. This means that the EOM cannot be like this:

while something; 
do
    command <<EOM
    Hello!
    EOM
done  

Instead, the EOM (or any other marked you use) needs to be the only thing on the line, so no whitespace or anything else before or after it. Like this:

while something; 
do
    command <<EOM
    Hello!
EOM
done  

Also, note that because of the reasons mentioned above, the leading whitespace will also be included, so that this:

c=0;
while [ $c -eq 0 ]; 
do
    cat <<EOM
    Hello!
EOM
    let c++
done  

Would print:

$ foo.sh
    Hello!

While this:

c=0;
while [ $c -eq 0 ]; 
do
    cat <<EOM
Hello!
EOM
    let c++
done  

Would print:

$ foo.sh
Hello!

Finally, when running your script, I get a different error:

$ foo.sh
I am currently in the following directory:
/home/terdon/foo
 
/home/terdon/scripts/foo.sh: line 108: warning: here-document at line 84 delimited by end-of-file (wanted `EOM')
/home/terdon/scripts/foo.sh: line 109: syntax error: unexpected end of file

This will be because I am not giving the same input data and, since you were not ending the EOM correctly, your data was probably being processed by the script and that's why you saw a different error. I expect my fix will get rid of it though, as it let me run your script through to the end on my machine.

muru avatar
us flag
Heredocs can be indented, when you use a leading hyphen before the delimiter word (e.g. `<<-EOM`), but can only use tabs for indentation. It's rather annoying.
terdon avatar
cn flag
@muru true, I never remember that, I just don't indent them and leave it at that. But good point, thanks.
in flag
Thank you so much sir. Now my problem has been resolved.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.