Shell Script: Assignment-Or Operator (a= b || c)
Asked Answered
S

3

6

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.

Shawnshawna answered 2/6, 2013 at 0:13 Comment(5)
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...Playbill
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)Playbill
@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?Shawnshawna
${1-"some default value"} is perfectly acceptablePlaybill
@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.Shawnshawna
S
9

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.

Sharronsharyl answered 2/6, 2013 at 2:16 Comment(2)
this looks promising, do you know anything about a non-bash assignment?Shawnshawna
This works with other bourne-type shells. csh is a different language altogether, one which I do not use.Sharronsharyl
P
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.

Playbill answered 2/6, 2013 at 3:5 Comment(2)
Note: $ is superfluous within $((...)). I believe it doesn't hurt, but it doesn't do anything.Villager
+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/explanationsShawnshawna
W
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 <<

Walking answered 2/6, 2013 at 0:52 Comment(4)
Those look like bitwise operators and not logical operators.Shawnshawna
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: pubs.opengroup.org/onlinepubs/009695399/utilities/…Walking
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.Walking
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.Shawnshawna

© 2022 - 2024 — McMap. All rights reserved.