3

I don't write a lot of Bash, so I'm a bit stumped as to how to fix this. I need to check whether a value returned from a command is greater than x. When it runs though I get [: -gt: unary operator expected which I'm unable to fix.

Here is my script,

#!/bin/sh
ERROR=0
PHPCPDLevel=100

# PHPCPD
echo "PHP CopyPaste Detection (Limit is at least ${PHPCPDLevel}%"
PHPCPD="phpcpd ."
if [[ `echo $PHPCPD | grep "%" | cut -d'.' -f1` -gt "$PHPCPDLevel" ]]
  then
    echo $PHPCPD
    ERROR=1
  else
    echo "... -> Only `echo $PHPCPD | grep "%" | cut -d'.' -f1`%"
fi

echo "Finished!"
exit $ERROR

Update: I think I've done it:

#!/bin/sh
ERROR=0
PHPCPDLevel=25

# PHPCPD
echo "PHP CopyPaste Detection (Limit is at most ${PHPCPDLevel}%)"
PHPCPD="phpcpd ."
PERCENTAGE=$($PHPCPD | grep "%" | cut -d'.' -f1)
if [ ${PERCENTAGE} -gt ${PHPCPDLevel} ]
  then
    echo $PHPCPD
    ERROR=1
  else
    echo "Only $PERCENTAGE%"
fi

exit $ERROR
James
  • 5,137
  • 5
  • 40
  • 80

2 Answers2

9

Remember that [ is a command. It maybe built into your shell, but it's still a command. It is expecting a particular set of parameters, and will give you an error when it gets something it doesn't understand. In fact, you can replace [ ... ] with test ... if that makes things a bit easier to understand:

For example:

test -gt 34

Will return:

bash: test: -gt: unary operator expected

Hmmm... same error message.

When you get things like this, you should use set -xv and set +xv around the problem area of your shell script. The set -xv will print out the shell command to be executed, and then will show you what the command line looked like after it has been mangled I mean interpolated by the shell.

I suspect that your error is:

if [ ${PERCENTAGE} -gt ${PHPCPDLevel} ]

That ${PERCENTAGE} is a blank value. If you use [[ ... ]] instead of [ ... ] you won't get that error. The [[ ... ]] is parsed a bit differently than [ ... ] because it's a compound command. The shell interpolations are done after the initial command is parsed, so it's a bit more forgiving if you miss a quotation mark or strings contain unexpected characters.

So:

ERROR=0
PHPCPDLevel=25

# PHPCPD
echo "PHP CopyPaste Detection (Limit is at most ${PHPCPDLevel}%)"
export PS4="\$LINENO: "     # Prints out the line number being executed by debug
set -xv                     # Turn on debugging
PHPCPD="phpcpd ."
PERCENTAGE=$($PHPCPD | grep "%" | cut -d'.' -f1)
if [[ ${PERCENTAGE} -gt ${PHPCPDLevel} ]]  # Use [[ ... ]] instead of [ .. ]
then
    echo $PHPCPD
    ERROR=1
else
    echo "Only $PERCENTAGE%"
fi
set +xv                     # Turn off debugging

exit $ERROR

Now, you'll see what the various commands that set environment variables are returning, and possibly see something you didn't quite expect.

David W.
  • 105,218
  • 39
  • 216
  • 337
4

You can't use double brackets [[ ... ]] in sh. Change your sheebang to

#!/bin/bash

or change the syntax to use single brackets [ ... ]. Don't forget to quote the terms inside the expression if you do that.

user000001
  • 32,226
  • 12
  • 81
  • 108