1

I'm using bash 5.0.7, and hope that I can expand the variable And="&&" and Or="||" in the double square brackets:

$ [[ 1 > 0 $And 1 < 0 ]] 
bash: syntax error in conditional expression
bash: syntax error near `$And`
$ [[ 1 > 0 ${And} 1 < 0 ]] 
bash: syntax error in conditional expression
bash: syntax error near `${And}`

I hope there's a way to do this because that will largely simplify one of my codes. And also, any explanations will be highly appreciated: I am really curious about how sh/bash works! Thank you very much in advance.

  • I don't think you can do that without eval (which might involve quoting hell with the other parts of your test). Can you show what you're trying to achieve in the end? Perhaps there might be some other way to do what you want. – ilkkachu Jul 22 '19 at 13:24
  • I'm really skeptical that would simplify your code. But if you're curious how bash works, then please notice that [[ a > b ]] will do a lexicographical comparison on its operands: [[ 2 > 11 ]] && echo 2 is greater than 11 (and to add insult to injury, they'll do it using the current locale ;-)). – mosvy Jul 22 '19 at 15:08
  • Even though it will be more verbose code, you're going to be better off just using an if or case based on $And rather than trying to shoe-horn it into the [[ command. – glenn jackman Jul 22 '19 at 16:13
  • I want my script to run between certain time, for example between 10am to 9:30pm: start=100000; end=213000. The problem is when end is over midnight, e.g. end=020000, I want $now to be larger than $start OR smaller than $end instead of AND. Is there another nonverbose way to do it? – Student Jul 22 '19 at 20:35
  • 1
    If end before start, add 24h to end. If now before start, add 24h to now. Then compare. – Kamil Maciorowski Jul 23 '19 at 1:06
1

It works with the test and [ builtin and -a (for &&) and -o (for ||):

$ and_or=-a
$ [ 1 -gt 0 $and_or 1 -lt 0 ] && echo yes || echo nope
nope
$ test 1 -gt 0 $and_or 1 -lt 0 && echo yes || echo nope
nope
$ and_or=-o
$ [ 1 -gt 0 $and_or 1 -lt 0 ] && echo yes || echo nope
yes
$ test 1 -gt 0 $and_or 1 -lt 0 && echo yes || echo nope
yes

(tested with bash 3.2.57 / 4.4.12 / 5.0.3)

As pointed out in the comments, I replaced the lexicographic comparison operators > and < with its arithmetic versions -gt and -lt.

But I would say this is quite a hack...

  • I always regard [ as a more primitive version of [[ so I did not expect that. Probably I should change my point of view.. – Student Jul 22 '19 at 20:37
  • 1
    @Student In some sense the approach works because [ is more primitive. In general it's a command or a builtin (the latter in Bash), so it gets its arguments like any other external command: they are processed in the shell before the command even runs and any of them can be taken from a variable. [[ is a keyword in Bash. It alters the parser: up to the next ]] the rules are somewhat different. This is obviously more complex. – Kamil Maciorowski Jul 23 '19 at 0:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.