BASH arrays and variables of variables in C++

Sometimes it is handy to protect long scripts in C++.

The following syntax works fine for simple commands:

#define SHELLSCRIPT1 "\
#/bin/bash \n\
echo \"hello\" \n\
"
int main ()
{
cout <<system(SHELLSCRIPT1);
return 0;
}

Unfortunately for there are problems for:
1d arrays: array=(a1 a2 a3)

error message: sh: 12: Syntax error: "(" unexpected
and
variables of variables:

var=VAR
k=0
VAR0=good
echo $VAR0; echo blah
eval "echo "\$$var$k""

error message: warning: unknown escape sequence: '\$' [enabled by default]

Please excuse my ignorance ... Is there a solution? What are the limitations of the aforementioned C++. Calling a Bash script from C++ is not the optimum solution for my case. The script needs to be inside the .cpp

Thanks

I am not sure what you are trying to do but is it this?
OSX 10.7.5, default bash terminal...

Last login: Sun Dec  1 15:55:50 on ttys000
AMIGA:barrywalker~> var=VAR
AMIGA:barrywalker~> k=0
AMIGA:barrywalker~> VAR0="Hello World."
AMIGA:barrywalker~> eval echo "$"$var$k
Hello World.
AMIGA:barrywalker~> _
1 Like

What do you mean by "protect"? Embedding shell scripts within C++ is not a standard practice IMO.

We can embed bash code in C++ with the system command or the define shellscript approach. When the bash code is a bit more advanced, for examples arrays or evaluation of variables of variables, errors appear.

An example of what I want to do:

Var1=good
Var2=excellent

I wish to echo Var1 and Var2 by using a two variable approach $var and $k. var=Var is stable and index "k" increases. This can be easily done in Bash:

var=VAR
k=0
VAR0=good
VAR1=excellent
for ((k=0; k < 2 ;k++))
do
eval "echo "\$$var$k""
done

This bash script I wish to embed in C++

Attempting to steer clear of as many C++ warnings as possible:-
Longhand OSX 10.7.5, default bash terminal...

#!/bin/bash --posix
> /tmp/vars.sh
chmod 755 /tmp/vars.sh
echo '#!/bin/bash --posix' >> /tmp/vars.sh
echo 'var=VAR' >> /tmp/vars.sh
echo 'k=0' >> /tmp/vars.sh
echo 'VAR0=good' >> /tmp/vars.sh
echo 'VAR1=excellent' >> /tmp/vars.sh
echo 'for k in $( seq 0 1 )' >> /tmp/vars.sh
echo 'do' >> /tmp/vars.sh
echo '        eval echo "$"$var$k' >> /tmp/vars.sh
echo 'done' >> /tmp/vars.sh
cat /tmp/vars.sh
echo ""
/tmp/vars.sh
echo ""

Results:-

Last login: Sun Dec  1 18:09:26 on ttys000
AMIGA:barrywalker~> chmod 755 var_to_newvar.sh
AMIGA:barrywalker~> ./var_to_newvar.sh
#!/bin/bash --posix
var=VAR
k=0
VAR0=good
VAR1=excellent
for k in $( seq 0 1 )
do
        eval echo "$"$var$k
done

good
excellent

AMIGA:barrywalker~> _

Of course this is generated by another shell script but it is a demo to try and overcome
any C++ warnings, errors and special directives...
As we have no idea of C++ code then the system() function seems the less problematic.

eval is evil

bash has got indirection

$ var=VAR
$ VAR0=good
$ VAR1=excellent
$ for ((k=0; k < 2 ;k++)); do nv="$var$k"; echo "$nv = ${!nv}"; done
VAR0 = good
VAR1 = excellent

@ wisecracker I think following problem he is facing, in preprocessor directives

$ cat test.cpp

// working
#define SHELLSCRIPT1 "\
#/bin/bash \n\
echo \"hello\" \n\
"

// Not working
#define test1 "\
#/bin/bash \n\
array=(a1 a2 a3) \n \
echo ${array
[*]} \n \
"

#include <iostream>
#include <cstdlib>
using namespace std;
int main ()
{
// working
cout <<system(SHELLSCRIPT1);

// whereas this is not working
cout <<system(test1);

return 0;
}

$ g++ test.cpp

$ ./a.out 
hello
sh: 2: Syntax error: "(" unexpected

Apart from changing lines 4 and 10 to "#!/bin/bash --posix" and cleaning up a bit, including removal of cout...

// Notice ! and --posix added to lines 4 AND 10
// Also cleaned it up a bit...
#define SHELLSCRIPT1 "\
#!/bin/bash --posix\n \
echo \"hello\"\n \
"

// Not working
#define test1 "\
#!/bin/bash --posix\n \
array=(a1 a2 a3)\n \
echo ${array[*]}\n \
"

#include <iostream>
#include <cstdlib>
using namespace std;
int main ()
{
// working cout removed
system(SHELLSCRIPT1);

// works on macbook pro cout removed
system(test1);

return 0;
}

Results...

Last login: Sun Dec  1 19:44:37 on ttys000
AMIGA:barrywalker~> g++ test.cpp
AMIGA:barrywalker~> ./a.out
hello
a1 a2 a3
AMIGA:barrywalker~> _

EDIT:
BTW cout removed because of RCs of 0 being printed to the window...

mute@thedoctor:~/temp/frad$ ./makecode < script > code.cpp
mute@thedoctor:~/temp/frad$ g++ code.cpp
mute@thedoctor:~/temp/frad$ ./a.out
VAR0 = good
VAR1 = excellent
mute@thedoctor:~/temp/frad$ cat makecode
#!/bin/sh

cat << '__EOF__'
#include <iostream>
#include <cstdlib>
#include <unistd.h>
using namespace std;

#define SHELL "/bin/bash"

const char shellcode[] = {
"\
__EOF__

sed -e 's/"/\\"/g' -e 's/$/\\n\\/'

cat << '__EOF__'
"
};

int main() {
        return execl(SHELL, SHELL, "-c", shellcode, NULL);
}
__EOF__

The shebang, #!/bin/bash ... is irrelevant; the system(3) library function will use /bin/sh . The OP's /bin/sh does not support the necessary features (arrays, indirect vars).

Regards,
Alister

3 Likes

The solution with

"$"

works as a dream. It is not which command is used, just

\$

is not accepted
The parenthesis used in a array declaration remain a problem. Should they be quoted, unquoted, backslashed?

---------- Post updated at 06:06 AM ---------- Previous update was at 05:38 AM ----------

Is there a work around the array issue? I need an 1d array. The only alternative are variable of variables , which work (the problem solved in this forum by wisecracker)

---------- Post updated at 06:32 AM ---------- Previous update was at 06:06 AM ----------

on ubuntu with g++ it does not work. If it works on Mac OS X perhaps is a matter of compiler. If yes is there a suitable c++ compiler on linux?