Syntax Error in simple bash script - bash

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.

Related

Verifying bash script inputs

I've just started using Linux as part of my computer science degree.
I'm writing some very simple Bash scripts and I've become a tad bit stuck.
I would like the script I'm attempting to write to be able to differentiate between "non valid inputs ie letters" from "valid inputs ie numbers from a specific range"
Currently the script "works" although I'm having troubles with another echo that I would like only to "echo" when the below line is "not true", is there a simple way to write this? I'm not specifically looking for efficient code, just code that I can learn from and understand at my amateur level.
So, long story short, is it possible to obtain information from the command line below, so that I can have a simple "not true" variable that I can use in another "else" or "elif" command?
For reference line 1 is to detect alphabetical inputs, and line 2 being the line of code I would like to write as "not true" for use in another part of my script.
let xx=$a+1-1 2>/dev/null; ret=$?
if [ $a -ge 7 ] && [ $a -le 70 ] && [ $xx -eq $xx ] && [ $ret -eq 0 ]
I'm not sure I'm explaining it very well, so any help would be appreciated. :)
Welcome to Stack Overflow. :)
Start by reading the docs. I don't mean that in any way to be mean - it's just the best way to go about this.
c.f. this manual
Then read through the BashFAQs
Also, this site is really your friend. Start by familiarizing yourself with how to ask a question well.
For your question, if I read it right:
typeset -i xx # accepts only digits now.
If the input is foo, the value defaults to 0, so now just check the range.
if (( xx >= 7 && xx <= 70 )); then : value is ok
else echo "Value must be a number from 7 to 70"
exit 1
fi
Good luck. :)
One problem with the "variable with integer attribute" is that it still doesn't protect you from invalid input:
$ declare -i aNumber
$ aNumber=1234X
bash: 1234X: value too great for base (error token is "1234X")
See 6.5 Shell Arithmetic for how bash interprets values to be numbers (scroll down to the paragraph starting with "Integer constants follow the C language definition")
In my experience, the best way to check for valid numeric input is with string-oriented pattern matching.
if [[ $1 =~ ^[+-]?[0-9]+$ ]]; then
echo "input $1 is an integer"
fi
In addition to extended regular expressions, bash's advanced pattern matching can also be used within [[...]]
if [[ $1 == ?([+-])+([0-9]) ]]; then
echo "input $1 is an integer"
fi
((...)) is preferred over let. See the let builtin
command for details.
Also the shellcheck wiki entry.

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 ]

could someone help me figure out why this doesn't work?

i=0
if [$i -eq 0]
then
echo "i is equal to 0"
else
echo "NOT EQUAL <><><><><><><><><><><><><><><><><><><>"
fi
it is part of a bash script and it always takes the else branch. I'm completely new to bash so its probably something silly
you need [ $i instead of [$i.
This is because the [ is a builtin command and $i should be it's first parameter. If you miss the space between command and parameter, then the shell will look for [$i command and after evaluation will tell you that there is no [0 command to be executed.
You need spaces after '[' and before ']'. '[' is a command.

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

#!/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 '=='

Resources