5

As the title describes, what's the proper way to do an or-assignment (eg a= b || c) in shell scripting, specifically csh vs bash? I cannot test this, so perhaps the example above works.

I thought this was pretty common in scripting languages, but for those that don't quite understand, the variable a will retain the value of b if truthy, otherwise the value of c. In the example b and c are expressions.

The usecase is typically to set to a to some kind of value if supplied, otherwise to use a default value (eg a= $1 || "Foo").


I'm not sure what the reason is for the close votes as this question is not:

  • broad
  • vague
  • incomplete

Please comment if you require some further explanation and need some amendment.

vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • Hard to know what you're going for here. In the shell, `||` operates on command exit statuses. `b||c` is a command that runs `c` if `b` fails. Did you mean it that way, and you want `a` to get the output of the command? Or are `b` and `c` supposed to be variables, in which case you should write them as `$b` and `$c` and the `||` operator will not apply... –  Jun 02 '13 at 00:17
  • In the second case, if what you want is to expand the value of `$b` but use the value of `$c` instead when `$b` is empty, you can use `${b-$c}` in a proper shell (i.e. not csh) –  Jun 02 '13 at 00:28
  • @WumpusQ.Wumbley During assignment `a` would be a variable and `b` and `c` would be an expression resulting in some value. Imagine passing an argument; Is `a= $1 || "some default value"` acceptable, or do you have to test the `$#` of arguments, or that `$1` is populated? – vol7ron Jun 02 '13 at 02:07
  • `${1-"some default value"}` is perfectly acceptable –  Jun 02 '13 at 03:09
  • @WumpusQ.Wumbley I'm going to give that a try. After re-reading my question, I guess I could make it more clear by asking in another way.. when I have a minute, I'll try to re-word it. – vol7ron Jun 02 '13 at 17:21

3 Answers3

8

For bash you want

a=${b:-$c}

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion

${parameter:-word}

If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted.

glenn jackman
  • 238,783
  • 38
  • 220
  • 352
4

I believe glenn jackman's got it, but I want to elaborate a little more than will fit in a comment.

Shell scripts aren't oriented around expressions. They're oriented around commands and words. Shell variables are strings by default (in the original Bourne shell, there was no way to create any other kind of variable). The RHS of an assignment isn't an "expression" the way you're thinking of it, and your b and c aren't "expressions" either, even if you wish they were.

The basic assignment syntax is

var=string

The right hand side is just a string. The shell offers a few kinds of expansions that can be used to build strings, which make it possible to do stuff like

var1=string
var2=$var1
var3="This is a ${var1}"
var4=$(ls | wc -l)
var5=$(($var4 + 1))

The value that is assigned to each variable is the string on the RHS with some expansions (marked by $) performed in it.

The last example, with $((...)), is the only one that really contains something that can be called an "expression". The double-parenthesized expansion works on arithmetic expressions, so this would be the thing to use if your b and c are numeric.

So you should stop thinking of your desired result in terms of an expression being evaluated with the two child expressions b and c as inputs, because the concepts just don't generalize that way in the shell language.

If b is a variable and you want to expand it with a default value to be used when the variable is unset, then use ${b-c}. If you also want the default value to be used when the variable is set but empty, then use ${b:-c}. The c in these examples is a string, and like all other strings in the shell it can be built with expansions:

i=3
var=""
echo ${var:-$(cat somefile)} # since var is empty, substitute file contents
echo ${var:-$(($i * $i))} # since var is empty, do some math instead

Now if your b is not a variable like $var, you'll probably find that none of the above applies! Because The ${...:-...} syntax is for variable expansion. You really will have to specify what b is, and you can't say "expression" because in the shell there's no such thing.

  • 1
    Note: `$` is superfluous within `$((...))`. I believe it doesn't hurt, but it doesn't do anything. – Kevin Jun 02 '13 at 03:35
  • +1; gave Glenn the cred for its brevity, though I'd still like to see a csh alternative for something fully complete. I may come back later and select your answer as it does have some additional helpful info/explanations – vol7ron Jun 03 '13 at 18:38
0

I'm guessing you mean this (in bash):

a=1
b=2
echo $(( $a | $b ))

Which results in 3: 1 | 2

The operators are |, ^, &, >>, and <<

jim mcnamara
  • 16,005
  • 2
  • 34
  • 51
  • Those look like bitwise operators and not logical operators. – vol7ron Jun 02 '13 at 02:06
  • Your question was not clear to me - those are bitwise operators. @wumpus q wumbley discussed || and &&, which are called lists. These are discussed in opengroup.org, under so-called POSIX shells. Go to paragraph 2.9.3 Lists. URL here: http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html – jim mcnamara Jun 02 '13 at 02:31
  • And glenn jackman below gave you shell parameter expansion, which varies a lot. Any of these could be considered an answer to what you seem to have asked. IMO. – jim mcnamara Jun 02 '13 at 02:39
  • All good jim. Just an FYI, when referring to other answers, it is generally unwise to refer to them spatially (eg order, placement, relative location). This is because answers can currently be sorted by *active*, *older*, or *votes*. – vol7ron Jun 03 '13 at 18:35