0

learning / relearning bash scripting. The following if - elif statement gets a conditional binary operator error on the first elif:

if [  $len -eq 1 ]; then 
grep -i -H $1 *.org
elif [[ [ $len -eq 2 ] -a { [ $1 == "keyword" ] -o [ $1 == "todo" ] } ]]; then

Yeah, I am an old noob, I am stumped. it looks ok to me. swgeek

Corrected some spacing errors, tried playing with parenthesis, searched here on conditional binary operator, and will continue that search, but nothing close enough for the light bulb to go on.

swgeek
  • 11
  • 4
  • 3
    You shouldn't have `[ ... ]` nested inside `[[ ... ]]`. Use one or the other, but not both. – Barmar Aug 17 '23 at 22:29
  • The rest of the elif-else block is uncorrected code and all the elif statements would be exceedingly similar. I need to correct the elif in order to correct the rest, thanks – swgeek Aug 17 '23 at 22:31
  • `-o` is not shell syntax, it's an argument to the `[` command. You can't use it in any context except where `test` or `[` is accepting arguments, and _even then_ it's marked obsolescent (the preferred syntax is combining multiple, smaller test commands). Same's true for `-a`. – Charles Duffy Aug 17 '23 at 23:08

2 Answers2

2

All the extra bracketing inside [[ ... ]] is invalid. It should be

elif [[ $len -eq 2 && ( $1 == "keyword" || $1 == "todo" ) ]]; then

Inside double square brackets you use parentheses for grouping, not square brackets or curly braces. And it uses C-style logical operators.

Or you can use standard single square brackets, but then you use && and || between the commands, not -a and -o (those are only used inside brackets). You also need ; before the closing }.

elif [ $len -eq 2 ] && { [ "$1" = "keyword" ] || [ "$1" = "todo" ]; }; then

Square brackets also allow using -a and -o between expressions inside a single set of brackets, but this is considered obsolete due to ambiguities with those operators, so it's preferable to use the conditional syntax above.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

You could write it for instance as

elif (( len == 2 )) && [[ $1 =~ ^(keyword|todo)$ ]]

This would make it easy to add more alternatives for $1 later on.

user1934428
  • 19,864
  • 7
  • 42
  • 87
  • Thanks gang, I am good with your help and suggestions – swgeek Aug 21 '23 at 03:33
  • With the second answer, I believe you meant $len, and I assume a typo. as for the rest, help my understanding. $1 matches (pattern) keyword or todo (should they not be in ") and I do not get the trailing $ - this overall problem is solved, now I am asking for my own understanding, and "reading" bash scripts. – swgeek Aug 21 '23 at 03:50
  • @swgeek : No, I meant a plain `len`. We are in numeric context after all. Using `$len` instead of `len` has the possible advantage, that if the variable is undefined or empty, we get a syntax error, while when writing a plain `len`, an empty variable would be interpreted as zero. $1 matches a word which is either _keyword_ or _todo_. It's just a normal regex match, as you know it from i.e. `egrep`. This means that if you want to extend it to several keywords, you just turn it into `^(keyword1|keyword2|....|todo)$`. – user1934428 Aug 21 '23 at 06:12