Angel
Angel

Reputation: 321

shellscript in C: using awk getting runaway string constant error

#define SHELLSCRIPT "\
#/bin/bash \n\
awk 'BEGIN { FS=\":\"; print \"User\t\tUID\n--------------------\"; } { print $1,\"\t\t\",$3;} END { print \"--------------------\nAll Users and UIDs Printed!\" }' /etc/passwd \n\
    "

void displayusers()
{
    system(SHELLSCRIPT);
}

The error message is:

awk: line 1: runaway string constant "User...

The bash cmd when run and works in the terminal is:

awk 'BEGIN { FS=":"; print "User\t\tUID\n--------------------"; } { print $1,"\t\t",$3;} END { print "--------------------\nAll Users and UIDs Printed!" }' /etc/passwd

I think somewhere when using \ to block out the various " for c it messed up my awk. But I'm not sure where. Ideas?

Upvotes: 0

Views: 457

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 755064

I simply took your string and used it in a printf() statement, and then analyzed the output:

#include <stdio.h>

#define SHELLSCRIPT "\
#/bin/bash \n\
awk 'BEGIN { FS=\":\"; print \"User\t\tUID\n--------------------\"; } { print $1,\"\t\t\",$3;} END { print \"--------------------\nAll Users and UIDs Printed!\" }' /etc/passwd \n\
    "

int main(void)
{
    printf("[[%s]]\n", SHELLSCRIPT);
    return 0;

}

Example run:

$ ./runaway
[[#/bin/bash 
awk 'BEGIN { FS=":"; print "User        UID
--------------------"; } { print $1,"       ",$3;} END { print "--------------------
All Users and UIDs Printed!" }' /etc/passwd 
    ]]
$

When I made the line ends visible (^J marks the end of line, ^I tabs), the problem is transparent:

[[#/bin/bash ^J
awk 'BEGIN { FS=":"; print "User^I^IUID^J
--------------------"; } { print $1,"^I^I",$3;} END { print "--------------------^J
All Users and UIDs Printed!" }' /etc/passwd ^J
    ]]^J

You have two occurrences of \n in the string which need to be \\n. It is up to you whether you change the appearances of \t to \\t; it works either way.

#define SHELLSCRIPT "\
#/bin/bash\n\
awk 'BEGIN { FS=\":\"; print \"User\t\tUID\\n--------------------\"; } { print $1,\"\t\t\",$3;} END { print \"--------------------\\nAll Users and UIDs Printed!\" }' /etc/passwd\n"

Using that in my program yields:

[[#/bin/bash^J
awk 'BEGIN { FS=":"; print "User^I^IUID\n--------------------"; } { print $1,"^I^I",$3;} END { print "--------------------\nAll Users and UIDs Printed!" }' /etc/passwd^J
]]^J

Note, in particular, the technique used to debug this. Print the data so you can see it precisely.

Upvotes: 1

wwkudu
wwkudu

Reputation: 2796

Haven't tested, but here's a useful-looking article just about this topic and it would appear that your choices are something along the following lines:

  • if you have different quotes surrounding the text, you don't need to escape the interior ones
  • you can use the same quotes surrounding and escape the interior ones
  • you can use octal sequences for the quotes, e.g. <\42>
  • if it get's too confusing, move the string into a separate file where quoting will not be an issue

Upvotes: 0

Related Questions