LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   syntax error near unexpected token in bash using perl (https://www.linuxquestions.org/questions/programming-9/syntax-error-near-unexpected-token-in-bash-using-perl-563355/)

kambrish 06-21-2007 12:10 AM

syntax error near unexpected token in bash using perl
 
Hi,
I am getting this problem while running the command from shell. If I run the command directly on command prompt, its running fine.
Here, i used the back slash also to skip the special purpose of single quote, but getting the below problem.

Command is:

sh -c '(perl -pi -e \'print "TextContents" if $.==13\' "/usr/local/etc/stunnel/stunnel.conf")'

bash: syntax error near unexpected token `"/usr/local/etc/stunnel/stunnel1.conf")''

If someone can help me, it would be great!
This command is for entering a line TextContents to a file stunnel.conf file at line number 13.
Regards Ambrish

chrism01 06-21-2007 01:58 AM

It looks like you've got a real newline break between the 2 lines there, which bash will interpret as separate cmds.
Either write it on 1 line or use '\' at the end of the 1st line, which bash will recognise as a line continuation.
It's important to know that nothing except the newline char must appear after the '\' .
Ps please post your distro in your profile.

bigearsbilly 06-21-2007 02:11 AM

messy, why don't you just make it a proper little script?

;)

kambrish 06-21-2007 02:12 AM

Hi Chris,
The command I gave is on one line only. Once again I give, its

sh -c '(perl -pi -e \'print "TextContents" if $.==13 \' "/usr/local/etc/stunnel/stunnel.conf")'

and the error which I am getting is :

bash: syntax error near unexpected token `"/usr/local/etc/stunnel/stunnel1.conf")''

So, i suppose its the filename at the end with path which is not properly in quotes. But i am not getting exactly how to change this.

Also, i updated my profile but i am not sure what exactly is meaning of distro!
Regards Ambrish

kambrish 06-21-2007 02:16 AM

Billy,
Its part of one particular module wherein much more scripts are running, so i cannot make a separate script.
Its just one command which I am passing to another function. Thats why I need to do it in this way.
Regards Ambrish

kambrish 06-21-2007 07:15 AM

can someone update. the error is just coming, i suppose, while giving the file name in double quotes. But i am not getting, how to remove this!! :(

archtoad6 06-21-2007 07:34 AM

Why are you using perl, & its complexity, for something that is almost trivial w/ sed?

Code:

# set insert line #
L=13
# set insert text
I="TextContents"
# set insert file
F="/usr/local/etc/stunnel/stunnel.conf"

sed -i "${L}i${I}" ${F}

BTW, I suspect the cause of your problem is shell quoting rules. Since I do not understand what difference you by "from shell" compared to "directly on command prompt". To me, both mean the same thing. Did you mean "from shell" to mean "inside a script"?

2nd, why are you using sh -c, rather than bash -c, your script is, after all, a bash script? In fact why are you using either? -- Can't you just put the perl command directly into the script?

Next, why the parentheses? I don't think they are normal w/ [ba]sh -c.

Finally, once again, why even use perl for this. To my way of thinking, it's swatting flies w/ a sledge hammer.

kambrish 06-21-2007 07:57 AM

Rick,
Your queries are quite correct but its a project which is already running and its already developed by someone else. We are in maintainence phase wherein need to do these updates.
Per ur queries:
Did you mean "from shell" to mean "inside a script"?
==> Yes!!

2nd, why are you using sh -c, rather than bash -c, your script is, after all, a bash script? In fact why are you using either? -- Can't you just put the perl command directly into the script?
==> Project is already developed. We need to do this small change.

Next, why the parentheses? I don't think they are normal w/ [ba]sh -c.
==> I can give my command only in parentheses as the command is passed on to some other function which is running this command.

Finally, once again, why even use perl for this. To my way of thinking, it's swatting flies w/ a sledge hammer.
==> Perl is already used in this project, so i have to use it!!
Regards Ambrish

bigearsbilly 06-21-2007 08:12 AM

I wouldn't call that a complex perl script.
also sed -i is not portable.
:)

archtoad6 06-21-2007 08:32 AM

Let me clarify: I wasn't saying that that snippet of perl was complex, but rather that perl itself is a complex language.

As for sed -i not being portable, that can be worked around w/ temp files -- which might be a safer way of doing things anyway.


So you/we are stuck w/ what is there. :)

General trouble shooting Q's:
Is this breakage a recent occurrence?
If so, can you think of anything else that changed around the same time that might be the cause?

Based on your clarification (for which, thanks), you're going to have to trouble shoot in place or in a dummy test script. It might help if you would outline the scripts/programs involved & who is passing what to whom. I think you are going to have trace what has become of your values vis-a-vis quoting rules at each step of the way. I suspect you're going to be reading the bash, & maybe other, man pages more than once.

It would also be helpful to know what you are allowed to change & what is off-limits.

wjevans_7d1@yahoo.co 06-21-2007 10:28 AM

That's funny. When I copy and paste your original problem line

Code:

sh -c '(perl -pi -e \'print "TextContents" if $.==13\' "/usr/local/etc/stunnel/stunnel.conf")'
into an xterm window, it neither is free of syntax errors (as it was for you on the command line) nor gives the error message

Code:

bash: syntax error near unexpected token `"/usr/local/etc/stunnel/stunnel1.conf")''
Instead, it gives the error message

Code:

-bash: syntax error near unexpected token `)'
I'm curious as to whether you copied and pasted accurately at all points. Be that as it may, let's work with what we have.

I did the following at the command prompt. Note which commands responded with Thursday when I asked for yesterday. (All of them either do that or fail completely, except the first one, which doesn't invoke sh at all.)

Code:

wally:~/thursday$ date
Thu Jun 21 07:57:31 PDT 2007
wally:~/thursday$ date -d yesterday
Wed Jun 20 07:57:39 PDT 2007
wally:~/thursday$ sh -c date
Thu Jun 21 07:57:50 PDT 2007
wally:~/thursday$ sh -c date -d yesterday
Thu Jun 21 07:57:55 PDT 2007
wally:~/thursday$ sh -c 'date'
Thu Jun 21 07:58:03 PDT 2007
wally:~/thursday$ sh -c 'date -d yesterday'
Thu Jun 21 07:58:07 PDT 2007
wally:~/thursday$ sh -c '(date)'
Thu Jun 21 07:58:12 PDT 2007
wally:~/thursday$ sh -c '(date -d yesterday)'
-d: -c: line 2: syntax error: unexpected end of file
wally:~/thursday$ sh -c "date"
Thu Jun 21 07:58:22 PDT 2007
wally:~/thursday$ sh -c "date -d yesterday"
Thu Jun 21 07:58:27 PDT 2007
wally:~/thursday$ sh -c "(date)"
Thu Jun 21 07:58:31 PDT 2007
wally:~/thursday$ sh -c "(date -d yesterday)"
-d: -c: line 2: syntax error: unexpected end of file
wally:~/thursday$

Since it's documented that bash works one way when invoked as sh and another way when invoked as bash, let's invoke it as bash:

Code:

wally:~/thursday$ date
Thu Jun 21 08:05:04 PDT 2007
wally:~/thursday$ date -d yesterday
Wed Jun 20 08:05:09 PDT 2007
wally:~/thursday$ bash -c date
Thu Jun 21 08:05:14 PDT 2007
wally:~/thursday$ bash -c date -d yesterday
Thu Jun 21 08:05:20 PDT 2007
wally:~/thursday$ bash -c 'date'
Thu Jun 21 08:05:27 PDT 2007
wally:~/thursday$ bash -c 'date -d yesterday'
Wed Jun 20 08:05:32 PDT 2007
wally:~/thursday$ bash -c '(date)'
Thu Jun 21 08:05:36 PDT 2007
wally:~/thursday$ bash -c '(date -d yesterday)'
Wed Jun 20 08:05:41 PDT 2007
wally:~/thursday$ bash -c "date"
Thu Jun 21 08:05:46 PDT 2007
wally:~/thursday$ bash -c "date -d yesterday"
Wed Jun 20 08:05:51 PDT 2007
wally:~/thursday$ bash -c "(date)"
Thu Jun 21 08:05:57 PDT 2007
wally:~/thursday$ bash -c "(date -d yesterday)"
Wed Jun 20 08:06:01 PDT 2007
wally:~/thursday$

In summary, every invocation of bash that puts single or double quotes around the parameter to the -c option works, whether or not parentheses are used.

Bingo. Your first change is from invoking sh to invoking bash.

But wait. There's more.

You should be aware of the way bash works with single and double quotes. The normal escape mechanism with backslash ("\") doesn't work as you'd think inside single quotes. Try these at the command line:

Code:

echo '\''
echo '\"'

(If you find yourself stuck in midcommand on the first of these, enter a Ctrl-D on a line by itself, and you'll get out again.)

No, you want double quotes around the whole thing (that is, a double quote just after the "-c " and a double quote at the end of the whole command. If you do this, you'll want to escape (precede with backslash) the dollar sign ("$") and every inner double quote, but no inner single quote.

So your command will look like this:

Code:

bash -c "(perl -pi -e 'print \"TextContents\" if \$.==13' \"/usr/local/etc/stunnel/stunnel.conf\")"
I tried this (but with a shorter file name), and it worked.

But you can also lose the parentheses. The effect of single parentheses is to fire up a new shell, but you're doing that already. That leaves you with:

Code:

bash -c "perl -pi -e 'print \"TextContents\" if \$.==13' \"/usr/local/etc/stunnel/stunnel.conf\""
I tested that one also (with a shorter file name). You also don't need the quotes around the filename. This leaves you with:

Code:

bash -c "perl -pi -e 'print \"TextContents\" if \$.==13' /usr/local/etc/stunnel/stunnel.conf"
I tested that one also (with a shorter file name).

Try these changes both on the command line and in your script.

Hope this helps.

wjevans_7d1@yahoo.co 06-21-2007 10:36 AM

Oh. And.

"Distro" is slang for "distribution". See the other posts in this thread for examples.

I re-read what I wrote, and have to ask: Why is it again that you need parentheses in the -c option? Can you be more specific?

archtoad6 06-21-2007 02:56 PM

Great analysis, wish I understood bash quoting well enough to have written that.

kambrish, I know you may be asleep, but please post back soonest.

kambrish 06-21-2007 11:01 PM

wjevans,
Thanx alot for the wonderful explanation. I tried it (from command line) and it worked!! Indeed, i am not an expert in shell, but your explanation has helped alot.
But let me give u little explanation of how its going in code and why I am using sh -c instead bash:

My code looks as below:

$exec_info = ginstall_common::execute_backquoted_command(
"perl -pi -e \'print \"TextContents\" if \$\.==13\' \"\/usr\/local\/etc\/stunnel\/stunnel1.conf\"",
);

The command goes like this in the function execute_backquoted_command

Now, if you see part of execute_backquoted_command where the above command is taken, it looks like below:

verbose::verbose(3, "sh -c '(@{commands_list})' " .
"> $ginstall_common::stdout_capt_fname 2> $ginstall_common::stderr_capt_fname");


So, here sh -c is coming which I cannot change as it impacts other modules too. For me only option is to pass the command to the function.

Ok, if this sh -c solution doesnt work, is there any other way or any other single command by which I can insert text contents at some particular line?
Kind Regards Ambrish

wjevans_7d1@yahoo.co 06-22-2007 06:34 AM

Quote:

Now, if you see part of execute_backquoted_command where the above command is taken, it looks like below:

verbose::verbose(3, "sh -c '(@{commands_list})' " .
"> $ginstall_common::stdout_capt_fname 2> $ginstall_common::stderr_capt_fname");


So, here sh -c is coming which I cannot change as it impacts other modules too. For me only option is to pass the command to the function.
I'm not sure I can help very much here. I have two suggestions, both of them possibly quite lame.

The first is this: I cannot imagine that changing the function to use bash instead of sh would harm other users, unless the software is also being used where bash is not available. Is there any way you can push through a change to the function? (I realize that what I'm asking is often foolish in a larger software environment.)

The second is this: If you can't or shouldn't change the function, can you add a new one which uses bash instead of sh?

As I said, lame, but ... (sigh)

EDIT:

I just thought of a third way.

Since it appears that passing parameters works with bash but not with sh (see my example above with Wednesday/Thursday), and you're restricted to using Perl, is there any way you can write a special-purpose Perl script which performs the file modification and uses environment variables rather than command-line parameters?


All times are GMT -5. The time now is 06:07 PM.