2

I am using ubuntu and using "/bin/bash" as my default bash. I have a simple c program (test_arg.c) that prints the arguments.

#include <stdio.h>

void
main(int argc, char **argv)
{
    for(int i=0; i < argc; i++) {
        printf("arg[%d]:%s \n", i, argv[i]);
    }
}

When I try to pass an argument that has a double quote, it works fine.

ubuntu@ubuntu:~$ ./test_arg.out 1 2 3 "4 5 6"
arg[0]:./test_arg.out
arg[1]:1
arg[2]:2
arg[3]:3
arg[4]:4 5 6

If I use a bash variable to store the arguments then it doesn't work as expected.

ubuntu@ubuntu:~$ arg="1 2 3 \"4 5 6\""
ubuntu@ubuntu:~$ ./a.out $arg
arg[0]:./a.out
arg[1]:1
arg[2]:2
arg[3]:3
arg[4]:"4
arg[5]:5
arg[6]:6"

I have to use a variable to store the arguments. I tried different options but failed. Appreciate any suggestions.

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
ABCDEFG
  • 187
  • 3
  • 11
  • This is not a C program, it's a bash problem. It's a problem with all sh-based shells, including bash. These shells perform quote handling *before* they expand variables. So when a shell variable contains quotes, you don't get what you want. – Steve Summit Apr 24 '18 at 23:32
  • So there is no solution? – ABCDEFG Apr 24 '18 at 23:34
  • Sometimes you can get around this problem using `eval` (which causes the shell to perform a whole nother round of command line evaluation, meaning that you get a second try at quote handling after your variable is expanded), but this usually then causes additional problems with unwanted extra evaluation, necessitating confusing extra quoting, which can end up being far more trouble than it's worth. – Steve Summit Apr 24 '18 at 23:34
  • There are some other tricks you can use, but I'm not remembering the details just now. Perhaps someone else monitoring the bash tag will have a suggestion. – Steve Summit Apr 24 '18 at 23:37
  • As Steve mentioned, you can use `eval`. Example: `eval ./a.out $arg` – builder-7000 Apr 24 '18 at 23:39
  • Use of "eval" command didn't work.. ubuntu@ubuntu:~$ eval ./a.out $arg arg[0]:./a.out arg[1]:1 arg[2]:2 arg[3]:3 arg[4]:"4 arg[5]:5 arg[6]:6" ubuntu@ubuntu:~$ – ABCDEFG Apr 24 '18 at 23:40
  • 2
    Read [BashFAQ #50](http://mywiki.wooledge.org/BashFAQ/050), which discusses this in detail, along with several best-practice fixes. `eval` is *not* one of those best-practice approaches; it can be made to work, but is inherently risk-prone, as described in [BashFAQ #48](http://mywiki.wooledge.org/BashFAQ/048); consequently, its use is heavily frowned on. – Charles Duffy Apr 25 '18 at 00:00
  • 2
    One approach that *is* a best practice is to use an array: `arg=( 1 2 3 "4 5 6" ); ./a.out "${arg[@]}"` – Charles Duffy Apr 25 '18 at 00:02
  • @ABCDEFG, ...to be clear, by the way -- **it would be very undesirable** for shells to behave any other way, as it would make it impossible to handle untrusted data securely if syntax contained in that data was honored on expansions. Consider if you have a variable `s='$(rm -rf ~)'` -- surely you want to be able to `echo "$s"` without running that code, but if all parameter expansion parsed data as syntax... **boom**. – Charles Duffy Apr 25 '18 at 00:55

0 Answers0