Bash Unary Operator Expected - bash

Okay, so within my script (this is my first time working with Bash) I am being met with two unary operator expected errors. The code itself is actually working fine, but it's presenting me with these errors at runtime:
[: !=: unary operator expected
For the line:
if [ ${netmask[1]} != "" ]; do
So for the first error, it's thrown when ${netmask[1]} is "" (null). I have tried multiple ideas and still can't get it to work without returning that error in the process.
I solved it by adding quotation marks (grrr)
if [ "${netmask[1]}" != "" ]; do

If you want to check for the null value for a variable, use the -z operator:
if [ -z "${netmask[1]}" ]; then
On example:
VAR=""
if [ -z "$VAR" ]; then
echo This will get printed
fi
Please note the parentheses around the variable: "$VAR".

Related

Why do I get unary operator expected?

So I am busy creating a rm function or I guess that is what it's called.
After executing the script and typing rm I get this error:
bash: [: ==: unary operator expected
My code is:
rm(){
if[ "$#" == "-u" ];
then
echo "Do something amazing."
else
echo "Boring"
}
I have even tried replacing the == with -eq but I still get the same error.
How to fix this?
P.S. when I type rm -u I don't get the error the code runs fine.
"$#" expands to all the arguments of the function, each separately requoted. If there are no arguments, it expands to an empty string, and the if statement becomes.
if [ == "-u" ]
which is not valid because there's nothing before ==. You would also get an error if you gave multiple arguments to the function; if you do rm -x -y it becomes
if [ "-x" "-y" == "-u" ]
Use "$*" instead of "$#" to get all the arguments as a single string.

if elif else construct gives an error albeit working as expected

I have this function:
function updateConfigFile()
{
# set -x
local CONTROLLER=$1; shift
local IP_ADDRESS=$1; shift
local FILE=$1; shift
if [ $1 -eq 0 ]; then
local FORE_STATEMENT=""
elif [ ! -z "$1" ]; then
local FORE_STATEMENT=$1
else
local FORE_STATEMENT="export"
fi
local NEW_RECORD="${FORE_STATEMENT} ${CONTROLLER}=${IP_ADDRESS}"
echo $NEW_RECORD
}
The echo output seems to be as expected whatever I use as 4th argument, including omitting it (FORE_STATEMENT will then be the default "export" value). the problem is that if the parma is not an integer bash gives an error at the first expression of the "if" construct (but continues to process correctly the rest of the construct).
if parma4 is a string I get:[integer expression expected]
if I omit it I get -eq: unary operator expected
I understand the reason of the error, but... can I ignore it since the output seems to be always correct?

null check throws unary operator error

I am tying to check if a variable is null, It throws the below error. I have tried the below combinations but it says the same error. I am trying to find out the files in a folder
cmd="ls -tm"
output=$($cmd)
echo $output // doesn't print out anything as the folder is empty
if [ $output != "" ];
For the below one it goes to the loop
if[ -z $output ];
Error output:
line 25: [: !=: unary operator expected
Any suggestions for handling this?
Have you tried using if [ "$output" != "" ]; instead of if [ $output != "" ];?
To expand on #Quine's suggestion, if $output is null, your if statement expands to
if [ != "" ];
which makes bash think an argument is missing. Quoting the parameter name overcomes this.

"" on $1, why does bash behave like this?

if a script has
if [ $1 == "-?" ]; then #line 4
echo "usage: ...."
fi
when the script get runs without any parameter, it will complain that
./script.sh: line 4: [: ==: unary operator expected
but if instead
if [ "$1" == "-?" ]; then #line 4
echo "usage: ...."
fi
then everything's fine
why is that?
thanks
If the first argument is missing or empty, your first script evaluates to:
if [ == "-?" ] ; then
... which is a syntax error. As you noticed, to prevent that you need to make use of "", then it evaluates to:
if [ "" == "-?" ] ; then
AFAIK this is due to the way the original Bourne shell was working. You should make it a habit of enclosing variables in "" to also work correctly with arguments that have spaces in it. For example, if you would call your script like this:
./myScript "first argument has spaces"
Then your first script would evaluate to:
if [ first argument has spaces == "-?" ] ; then
which is also a syntax error. Also things like rm $1 will not do what you want if you pass filenames with spaces. Do rm "$1" instead.
Because [ replaces the values before executing. [[ doesn't, so will work as expected.

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

Resources