Question

Certain languages like awk script allow for conditional assignments. For example, say you had a list file in the format:

<item name, no spaces> <price as float>

e.g.

Grape 4.99
JuicyFruitGum 0.45
Candles 5.99

And you wanted to tax everything over $1... you could use the awk script:

awk '{a=($2>1.00)?$2*1.06:$2; print a}' prices.data

...which uses conditional assignment to shorten the syntax.

But say you wanted to also offer $1 off all items over $20 and $2 off items over $40. Well in a language like c you would typically do something like:

if (price > 40.00) {
   price-=2; 
   price *= 1.06; 
}
else if ( price > 20.00 && price <= 40.00 ) {
   price--; 
   price *= 1.06; 
}
else if ( price > 1.00 ) {
   price*=1.06;
}

... well I discovered you could kludge awk or other scripting languages into COMPOUND assignment. e.g.:

awk '{a=($2>1.00)?($2>20.00)?($2-1)*1.06:($2>40.00)?($2-2)*1.06:$2*1.06:$2; print a}' prices.data

My questions are that

a) is compound assignment (like this) generally universally compatible with scripting languages that support conditional assignment?
b) Is there a non-kludge way to do multi-conditional assignment in awk script?

To clarify: I am talking exclusively about the shorthand for assignment (<...>?<...>:<...>;, not traditional conditional assignment, which I already know how to do c-like compound assignment for in Awk script. As a side note, as to why I might use shorthand, I think the merit is obvious -- that it's short. But like regexes, you might want to write a good description of what your confusing syntax does for posterity's sake.

Was it helpful?

Solution

a)

Bash, ksh and zsh support compound conditional (ternary) operators (Bash doesn't do floats, though):

for i in {3..5}; do for j in {2..6}; do for k in {2..4}; do
    (( a = i > j ? i > k ? j > k ? i * j : i * k : j * k : 0 ))
    echo $a
done; done; done

PHP's ternary operator syntax is similar.

Python's is quite different:

a = b if c else d if e else f if g else h

Bash, et al, and Ruby (which also supports the ?: form) support this style (showing Bash's version):

[[ condition ]] && do_if_true || do_if_false

which can be done in a compound form. This can perform actions in addition to assignments.

b) no, not without explicit if/else (or resorting to even more kludginess creativity.

OTHER TIPS

Actually, C has the ? operator too, so you could do the same (fugly) thing with C.

However, you are essentially making write-only code there. If you hadn't told me what that awk statement did, it would be very difficult to figure it out. Why not just go ahead and use if?

You'll thank yourself in 6 months when you discover a need to tweak it.

(a) I think so

(b) Yes


As it happens, your "C" code is almost legal awk. The following slightly tweaked version works just fine as an awk program...

/./ {
  price = $1
  if (price > 40.00) {
     price -= 2 
     price *= 1.06 
  } else if ( price > 20.00 && price <= 40.00 ) {
     price-- 
     price *= 1.06 
  } else if ( price > 1.00 ) {
     price *= 1.06
  }
  printf("%6.2f\n", price)
}

I took the semicolons out, but nothing bad happens if you leave them in...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top