views:

41

answers:

3

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.

A: 

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.

T.E.D.
If you understand the syntax, you could break it out into a series of if statements and it shouldnt be too hard to figure out. Plus that's what comments in your file of one-liners are for :) I like it because its SHORT, but I'd prefer a proper compound conditional shortening if there is such a thing...
Jason R. Mick
A: 

(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...

DigitalRoss
err... I was referring exclusively to the assignment shorthand (<...>)?<...>:<...> ... I already know how to compound assign using traditional conditionals. I've added extra clarification to my post just so no one else is confused like you were.
Jason R. Mick
OK, understood, but you did say "in a language like C", and it was kind of cool that your "C" worked in `awk`. Obviously, there is a general equivalence in `?:` vs `if-then-else`. Now, the cool frontier is in something like Ruby that lets you say `(x?y:z; whatever; if x ...; and_do_something_else)` and you can put that just anywhere, including arbitrary statements in expressions in ((((())))) ...
DigitalRoss
Yea I see where that was a bit confusing... sorry about that. That sounds like an interesting tool for compound execution in Ruby...
Jason R. Mick
+1  A: 

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.

Dennis Williamson
Wow great answer! You, sir, are truly a scripting expert. Just the kind of info I was overview for... Have you ever thought of writing a scripting book? :P
Jason R. Mick
@Jason: The thought has crossed my mind, but there's no money in books any more.
Dennis Williamson
A website perhaps then? :P Seems like theres someway to put that educational talent to good use monetarily. The frequent (free) help is appreciate though!
Jason R. Mick