Cygwin bash syntax error - but script run perfectly well in Ubuntu - bash

#!/bin/bash
if test "$#" == "4"; then echo "$*"; else echo "args-error" >&2; fi;
This little code snippet troubles me a lot when I tried to run it on both Ubuntu and Cygwin.
Ubuntu runs bash version 4.0+ whereas Cygwin runs 3.2.49; But I reckon version collision shall not be the cause of this, this code runs well under fedora 10 which is also using bash version 3.+
So basically I am wondering if there is a way to code my script once and for all so there are not to have this awful issue later on.
Many thanks in advance.
Edited : I don't have Cygwin by hand at the moment but from my memory, it keeps saying something like couldn't resolve undefined token "fi" something like that.
Edited : well,the original form is like this, just found from server :
#!/bin/bash
if ["$#" == "4"];
then echo "$*";
else echo "args-error" >&2;
fi;
Console complains :
$ ./test.sh 1 2 3
./test.sh: line 2: [3: command not found
args-error
I am also wondering how come that stderr says something goes wrong - command not found - but can still print out the answer?

You need whitespace around the [ and ].
#!/bin/bash
if [ "$#" == "4" ];
then echo "$*";
else echo "args-error" >&2;
fi;

Updated answer:
You need a space after [ otherwise ["$#" is evaluated to for example [3 which doesn't exist. Try this:
if [ "$#" == "4" ];
then echo "$*";
else echo "args-error" >&2;
fi;
It works for me. I would guess that you are getting an error like this:
test.sh: line 2: $'\r': command not found
test.sh: line 3: $'\r': command not found
This can happen because you have edited the file using Windows-style line endings but Bash expects Unix-style line endings. To fix the file, try running this command:
dos2unix test.sh
You of course need to change the filename to the actual filename of your script.

In your edit to show the 'original form' the problem would seem to be that you're missing a space between the [ and the "

try to use operator '=' instead of '==' . And also add one space after [ and another before ] as folowing
if [ "$#" = "4" ];
then echo "$*";
else echo "args-error" >&2;
fi;
Or even try '-eq' instead of '=='
if [ "$#" -eq "4" ];
Because in some systems, it does not accept the operator '=='

Related

Why does the same if condition work one time and another time doesn't?

Hi Stackoverflow community.
I have a question to (probably sporadic) problem.
A bash if-condition for non-equal strings yields one time results another time the error message "[[: command not found".
Sample code of test.sh:
#! /bin/bash
arg1=$1
echo -e "arg1: " $arg1
if [[ $1 != "test" ]] && [[ $1 != "testing" ]]; then
echo "test1"
fi
if [[ $1 != "test" ]] && [[ $1 != "testing" ]]; then
echo "test2"
fi
output:
$ ./test.sh foo
arg1: foo
test1
./test.sh: line 10:  [[: command not found
As you see the second echo command will never be reached.
I tested the snippet on MacOS bash (GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)) and on Linux bash (GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)) and could confirm that error every time.
(my best guess was that there some kind of encoding problem but I could not confirm that yet).
Thank you in advance for any help and/or pointers.
Thanks to #gbajson and #I0b0 the reason was found:
Error on my part I included an non-break space (Oct 0240, Dec 160, Hex 0xA0, HTML ) in line 11 right before "[[".

Will bash script pre-parse the syntax?

I am running bash script that needs to run different code for SunOs and Linux and I am getting the syntax error from the part of the code that not supposed to be true. I did not expect that since I thought that Bash works as interpreter.
The bash version on SunOS is 2.5 and on Linux is 4.1. The syntax it complains about is only supported from 3.1 version.
I tried to disable the newer code with "else" clause but it looks like it still pre-parses.
Also my script has ":" instead of "#! /bin/sh" as first line.
test.sh:
:
echo "`uname`"
if [ `uname` = "SunOS" ]
then
echo "do old stuff"
else
echo "new stuff"
arr=($(grep "^X1" ../foo.txt | sed 's/.*=//'))
fi
The error is
> ./test.sh
SunOS
./test.sh: syntax error at line 8: `arr=' unexpected
If I comment error line then it will work fine:
:
echo "`uname`"
if [ `uname` = "SunOS" ]
then
echo "do old stuff"
else
echo "new stuff"
#arr=($(grep "^X1" ../foo.txt | sed 's/.*=//'))
fi
The result is
> ./test.sh
SunOS
do old stuff
My question is how do I fix this syntax error without commenting? I have to have "if/else" to be able to run this script on different machines.
That array syntax has been supported in bash since at least version 2; if you're getting errors there, it's because your script is not running under bash at all, but under some other shell. This probably has a lot to do with your script starting with : instead of a shebang line, meaning it's up to whatever runs the script to figure out what to run it with, with inconsistent results. I'd strongly recommend using a proper shebang line. If bash doesn't exist in a predictable location, you could use #!/usr/bin/env bash. If bash might not be in the PATH, you could use something like the script prologue here -- a #!/bin/sh shebang followed by commands to find and switch to bash.
As for the question about pre-parsing: yes, bash and other shells will parse all the way to the fi keyword before executing the if construct. They need to find the then, else, and fi keywords in order to figure out what they're going to execute and what they're going to skip, and in order to find those they have to parse their way to them.
You could stick the command in a temporary variable, and then execute the variable if your condition is true. I just ran the following on my system:
> if [ true ]; then echo hi; else [blah]=(--4); fi
-bash: syntax error near unexpected token `--4'
I get a syntax error as you describe. If I then do:
> if [ true ]; then echo hi; else var="[blah]=(--4)" && eval "${var}"; fi
hi
then it echos hi (no error). Finally if I do:
> if [ ]; then echo hi; else var="[blah]=(--4)" && eval "${var}"; fi
-bash: syntax error near unexpected token `--4'
Then it attempted to run the code, and generates an error based on trying to run the code.

Test bash command line arguments

I don't know bash well but this seems pretty basic, yet I'm stuck on it. I'm using the bash installed on Mac OS X. I'm simply trying to test 1 command line argument and this is what I have and it doesn't work.
if [$1 -eq 'clean']
then
echo "Your argument is 'clean'!"
fi
Every time I've tried it, bash gives me a command not found error.
I'm obviously doing something wrong, what is it?
Couple of issues here:
Spaces around [ and ] are required in shell
-eq is used for comparing integers not for strings
Try this instead:
if [[ "$1" == "clean" ]]; then
echo "Your argument is 'clean'!"
fi
If you are using bash then [[ and ]] are more efficient than [ and ]

passing variables to a bash script

I have a bash script "test.sh" and one parameter I want to use is --no-email.
when I run test.sh --no-email, everything works as expected and I do not receive an email status report.
However what I really want to run is "test.sh test.cnf" where the --no-email parameter is stored in the test.cnf file along with a load of other parameters. I cant for the life of me get this to work. Perhaps I am being completely stupid and not understanding?
Many thanks
echo $*|grep -se '--no-email'&>/dev/null
SEND_MAIL=`echo $?`
echo -e "DEBUG: \$*=$*"
if [ ! "$SEND_MAIL" == "0" ]; then
echo 'Mail would have been sent!'
else
echo 'NO MAIL WOULD HAVE BEEN SENT!'
fi
If you cannot modify the script test.sh to support this you still can use this syntax to fetch parameters from a config file:
test.sh $(<test.cnf)
If this assumption is not true, i.e. you want to modify test.sh itself to support this then you have to be more specific about what happens inside test.sh.
Edit: Now the content of test.sh has been added to the question. Starting from there the most simple thing to do would be like this:
grep -sqe '--no-email' "$*"
SEND_MAIL=$?
But you wrote that you have a bunch of other paramaters. Doing a grep for each one might be inconvenient. In this case you can loop over the word of a cnf file like this:
#!/bin/bash
while read line; do
for word in $line; do
echo "examing $word"
case "$word" in
--no-email)
SEND_MAIL=0
;;
--no-foo)
NO_FOO=0
;;
*)
echo 1>&2 "WARNING: Unknown parameter: $word"
;;
esac
done
done < "$1"

Syntax Error in simple bash script

Hello im new to bash scripting, i have a simple program which is not working for me. I assume its a syntactical error.
#!/bin/bash
#example1.sh
read Age
if ["$Age" -lt "18"]; then
echo "You must go to school"
fi
When i input a 1 it says [1: command not found
You need spaces:
if [ "$Age" -lt "18" ]; then
(Summary: Bash syntax rules are appalling.)
#!/bin/bash
#example1.bash
read Age
if(($Age < 18)); then
echo "You must go to school"
fi
This code works when it is run in bash. Bash and sh are not completely the same.

Resources