billy
billy

Reputation: 29

How to fix bad substitution error in bash?

I am trying to write a bash script where the user enters a class name and it makes the proper .h and .cpp files.

I have got most of it working however when I run it, I get the error:

./makeClass.sh: line 20: #include ${className.h}: bad substitution

The .h file is generated with all content as expected whereas the .cpp file generation is aborted at that line.

I have tried to replace ${className.h} with $(className.h), but that did not work.

I also tried to concatenate the strings but I have had no luck.

Thank you for all of your help!

#!/bin/bash
echo "Please enter the name of the class to be created"
read className

touch $className.h
echo "#include <iostream>" >> $className.h
echo "#ifndef SICT_${className^^}_H" >> $className.h
echo "#define SICT_${className^^}_H" >> $className.h
echo "namespace sict {" >> $className.h
echo "class ${className^} {" >> $className.h
echo " " >> $className.h
echo "public: " >> $className.h
echo " };" >> $className.h
echo "}" >> $className.h
echo "#endif" >> $className.h
# Note: ${className^} converts the first letter to uppercase ${className^^}
# converts the whole string to upper case

touch $className.cpp
echo "#include ${className.h}" >> $className.cpp
echo "#include <iostream>" >> $className.cpp
echo "using namespace sict;" >> $className.cpp
echo "using namespace std;" >> $className.cpp
echo "namespace sict {" >> $className.cpp
echo "" >> $className.cpp
echo "}" >> $className.cpp

Error message: ./makeClass.sh: line 20: #include ${className.h}: bad substitution

Upvotes: 1

Views: 3063

Answers (2)

Avinash Yadav
Avinash Yadav

Reputation: 916

This will work Always

echo "#include \"$className.h\"" >> $className.cpp

Explationantion: As className.h is a variable use double-quote when using it and as here there were already double-quotes for echo, escape double-quotes for the variable.

Full Code

#!/bin/bash
echo "Please enter the name of the class to be created"
read className

touch $className.h
echo "#include <iostream>" >> $className.h
echo "#ifndef SICT_${className^^}_H" >> $className.h
echo "#define SICT_${className^^}_H" >> $className.h
echo "namespace sict {" >> $className.h
echo "class ${className^} {" >> $className.h
echo " " >> $className.h
echo "public: " >> $className.h
echo " };" >> $className.h
echo "}" >> $className.h
echo "#endif" >> $className.h
# Note: ${className^} converts the first letter to uppercase ${className^^}
# converts the whole string to upper case

touch $className.cpp
echo "#include \"$className.h\"" >> $className.cpp
echo "#include <iostream>" >> $className.cpp
echo "using namespace sict;" >> $className.cpp
echo "using namespace std;" >> $className.cpp
echo "namespace sict {" >> $className.cpp
echo "" >> $className.cpp
echo "}" >> $className.cpp

Upvotes: 0

L&#233;a Gris
L&#233;a Gris

Reputation: 19545

Your error is:

echo "#include ${className.h}" >> $className.cpp`
                          ^

It threats the whole className.h as the variable name, and the dot character. is not allowed in a variable name.

Also always add the -r flag to read, unless you want it to interpret escaping.

You can create your templates more clearly and efficiently with here-documents that expands bash variables values:

Although, in case you need to have an actual dollar sign $ literal, you need to escape it as \$, or bash will try to expand a variable name to its value.

#!/usr/bin/env bash

echo "Please enter the name of the class to be created"
read -r className

cat <<EndOfClassHeader >"$className.h"
#include <iostream>
#ifndef SICT_${className^^}_H
  #define SICT_${className^^}_H
  namespace sict {
    class ${className^} {

      public:
    };
  }
#endif
EndOfClassHeader

cat <<ENdOfClassCPP >"$className.cpp"
#include ${className}.h
#include <iostream>
using namespace sict;
using namespace std;
namespace sict {
}
ENdOfClassCPP

Upvotes: 2

Related Questions