29

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
  • 275,237
  • 103
  • 548
  • 598
myahya
  • 3,079
  • 7
  • 38
  • 51

5 Answers5

46

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
  • 54,094
  • 23
  • 70
  • 76
  • 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
34

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
  • 11,045
  • 8
  • 74
  • 149
SiegeX
  • 135,741
  • 24
  • 144
  • 154
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
  • 445,704
  • 82
  • 492
  • 529
6

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

SOUser
  • 3,802
  • 5
  • 33
  • 63
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
  • 346,391
  • 90
  • 374
  • 439