26

I have the following line as part of a much bigger bash script:

if [ `packages/TinySVM-0.09/bin/svm_learn 2>&1| grep TinySVM | wc -l | cut -c0-7 | sed 's/^  *//g'` -eq 1 ] 

upon running the script, I get:

./install.sh: line 219: [: -eq: unary operator expected

Where line 219 is the line above. Any suggestions for a fix?

fedorqui
  • 252,262
  • 96
  • 511
  • 570
myahya
  • 2,999
  • 7
  • 36
  • 51

5 Answers5

43

You can run your command without any additional syntax. For example, the following checks the exit code of grep to determine whether the regular expression matches or not:

if ! grep -q "$word" /usr/share/dict/words
then
    echo "Word $word is not valid word!"
fi
Alex Spurling
  • 51,267
  • 23
  • 67
  • 73
  • 1
    That's what I was looking for... – mmey Nov 15 '14 at 12:59
  • Is there any reason not to use this technique, because it is mentioned pretty seldomly? – Niklas Peter Feb 23 '16 at 09:05
  • 1
    Probably I found the reason myself: With grep that works well, but with other commands, that might output sth. (and not just return a code), this output will be printed to stdout. What is about ````if command >& /dev/null; then ...````? – Niklas Peter Feb 23 '16 at 13:37
  • If the command ouput something it is indeed better to use `if ! cmp foo.txt bar.txt > /dev/null 2> /dev/null ;then ...` – Richard Mar 01 '16 at 02:45
33

This happens when you are using the test builtin via [ and your left side expression returns NUL. You can fix this by the use of:

if [ x`some | expression | here` = x1 ]; then

Or, since you're already using bash you can use its much nicer (( )) syntax which doesn't have this problem and do:

if (( $(some | expression | here) == 1 )); then

Note that I also used $() for command substitution over backticks `` as the latter is non-POSIX and deprecated

Thomas Tempelmann
  • 10,222
  • 7
  • 66
  • 132
SiegeX
  • 128,491
  • 23
  • 138
  • 153
8

The error occurs because your command substitution returns nothing effectively making your test look like:

if [ -eq 1 ] 

A common way to fix this is to append some constant on both sides of the equation, so that no operand becomes empty at any time:

if [ x`packages/TinySVM-0.09/bin/svm_learn 2>&1| grep TinySVM | wc -l | cut -c0-7 | sed 's/^  *//g'` = x1 ] 

Note that = is being used as we are now comparing strings.

codaddict
  • 429,241
  • 80
  • 483
  • 523
6

Try [[ test_expression ]]; instead of [ test_expression ];

SOUser
  • 3,733
  • 4
  • 31
  • 61
6

You could add an "x" to both sides of the comparison or you could just quote the left side:

[ "$(command | pipeline)" = 1 ]

I don't understand what the cut and sed at the end are for. The output of wc -l in a pipeline is simply a number.

Dennis Williamson
  • 324,833
  • 88
  • 366
  • 429