0

The below is the snippet of my script which throws the error while running it:

echo "#include \"Factory.H\"" > $1
echo "#include \"Stub.H\"" >> $1
echo "#include \"Ref.H\"" >> $1

#
# a loop to include all of the headers for the stubs.
#
ARGS=("$@")
for ((i = 1; $i < $#; i=$i+2)) ; do 
    echo ${ARGS[$i]}
    echo "#include \"${ARGS[$i]}.H\"">> $1
done 

The error reported in the ARGS=("$@"), I could not figure out why this is being reported as an error. The script is invoked with the following input

..//scripts/makestubfactory ./obj/_stubfactory.C RegistryImpl_Stub "com.frco.fievel.comm.registry.RegistryImpl_stub" ObserverBrokerImpl_Stub "com.frco.fievel.observer.ObserverBrokerImpl_stub" SubjectAccessImpl_Stub "com.frco.fievel.observer.SubjectAccessImpl_stub"

Please shed some lights on how to sort out this issue.

3
  • Should you be quoting $# Commented Feb 13, 2017 at 3:24
  • $# doesn't need quoting. Commented Feb 13, 2017 at 3:35
  • The >> $1 part can be kept outside the loop for efficiency. done >> "$1". Commented Feb 13, 2017 at 3:46

2 Answers 2

3

You need to make sure that your script is run with the bash shell, since a standard Posix shell (which is what sh might be on your system) does not implement arrays. To do so, you should add a shebang line as the first line of your script:

#!/usr/bin/bash

The path /usr/bin/bash must be the full path to the bash executable, which might be in some other location on your machine. Some people prefer to use

#!/usr/bin/env bash

which will find bash wherever it is in the PATH, but requires env to be at the fixed location.

You can find the path to the bash executable from bash by using the command:

which bash

There are a number of improvements which could be made to this script, some of which I noted in a quick glance:

  1. You can use single quotes to avoid having to backslash escape the double quotes (but only if you don't have single quotes or variable expansions inside your strings). Variable expansions, on the other hand, should be quoted:

     echo '#include "Factory.H"' > "$1"
    
  2. Even better, use a here-doc to copy an entire template:

    cat >"$1" <<"EOF"
    #include "Factory.H"
    #include "Stub.H"
    #include "Ref.H"
    EOF
    
  3. You don't really need an array, since you can use bash's indirection operator to access command-line arguments:

    for ((i=2; i<$#; i+=2)); do
      echo "${!i}"
      echo "#include \"${!i}\".H" >> "$1"
    done
    

    Note the use of i+=2 rather than i=$i+2.

    Another solution, using printf to output all the arguments in one call:

    printf '#include "%s.H"\n%.0s' "${@:2}"
    

    This makes use of the fact that the shell printf utility keeps repeating the format until it has used up all the arguments, which can be very helpful. In this case, I use %.0s (i.e. print a string with maximum length 0) to not print the odd arguments. "${@:2}" is a bash extension which is like "$@" except that it starts with argument 2.

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

8 Comments

It doesn't seem to be an issue with the shebang line.
My script had #!/bin/sh at the top of the script hence I run in to the issue. Thanks for pointing out that "sh does not implement arrays". I changed the line #!/bin/sh to #!/usr/bin/env bash that works fine now.
@codeforester: Evidently on your system, sh is bash. Not everyone has their machine configured that way.
@rici - you are right. But, I read somewhere that bash would behave differently when it is invoked as sh. I wonder why that's not happening in my case.
@codeforester: "I read somewhere" is not a substitute for RTFM :)
|
-1

Try this:

echo "#include \"Factory.H\"" > $1
echo "#include \"Stub.H\"" >> $1
echo "#include \"Ref.H\"" >> $1

#
# a loop to include all of the headers for the stubs.
#
ARGS=("$@")
for ((i = 1; $i < $@; i=$i+2)) ; do 
    echo ${ARGS[$i]}
    echo "#include \"${ARGS[$i]}.H\"">> $1
done 

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.