1

I am modifying/re-writing some of the scripts written by former employees of my company and in one of the shell scripts I found the following line.

b=`benchmark=30;grep "Waiting for timer" wk.txt | awk -vbenchmark=$benchmark '$6 > benchmark' | wc -l`

But my bad, I couldn't figure out what the above line is trying to do. I am confused about the usage of 'benchmark' variable here. I created a dummy 'wk.txt' file with the following values and the when echoed, variable $b got the value 1 (which is just a line count of the output of the grep+awk command.

[sreeraj@server ~]$ cat wk.txt
24  here  above the Waiting for timer 37 make sure

Could someone explain what the script author is trying to do with the $benchmark?

awk man page says the below for -v, but I am not I understood what it does.

-v var=val
--assign var=val
          Assign the value val to the variable var, before execution of the program begins.   Such  variable  values  are
          available to the BEGIN block of an AWK program.
Sreeraj
  • 5,062
  • Could change the whole thing to b=$(awk -vbenchmark='30' '/Waiting for timer/&&$6>benchmark{x++}END{print x}' wk.txt) or if you didn't wnat a pointless variable b=$(awk '/Waiting for timer/&&$6>30{x++}END{print x}' wk.txt) –  Dec 10 '14 at 14:12
  • Thanks for all the replies. I re-wrote everything in Python. – Sreeraj Dec 10 '14 at 16:13

2 Answers2

3

If you do:

awk -v benchmark=30 '...'

That is the same as:

awk 'BEGIN{ benchmark = 30 } ... '

This is used to set an initial value for that variable.

Though I don't see why the author does:

benchmark=30; ... | awk -v benchmark=$benchmark ..

They might as well do:

... | awk -v benchmark=30 ..
muru
  • 72,889
  • That is, benchmark=30;grep "Waiting for timer" wk.txt | awk -vbenchmark=$benchmark '$6 > benchmark' | wc -l is the same as grep "Waiting for timer" wk.txt | awk -v threshold=30 '$6' , which is not returning anything other than a simple grep "Waiting for timer" wk.txt for me. Strange. – Sreeraj Dec 10 '14 at 10:51
  • @Sree Well, your input data might be such. The awk code is checking if $6 is greater than the assigned value of benchmark, and your example case has $6 > 30. (Any string starting with alphabets will be greater than "30", (or a any string composed only of digits).) – muru Dec 10 '14 at 10:55
  • Makes sense now. The comparison with 30 matches with the purpose of the script. By the way Murukesh, the speed at which you jump from 1000 to 2000 to 3000 is amazing. Keep it up :) – Sreeraj Dec 10 '14 at 11:35
2

The confusion may be caused by the fact that the original author used the same variable name for the shell:

benchmark=30;gr...

as he/she did inside awk:

awk -vbenchmark=$benchmark

which may or may not assign the value of the shell variable benchmark to the awk variable benchmark.

Once awk has this value (30 in this case), awk checks that the 6th column of your input file wk.txt is greater than this value:

$6 > benchmark

The test, using your example, is therefore the string comparison:

for > 30

which, while legal, doesn't really doesn't make much sense. Is the example input file a genuine example or just random test?

This evaluates to true, therefore awk prints the whole line to wc -l which counts the number of lines. As you only have one line in your input file, the count of lines where the 6th column is greater that 30 is 1.

This value is assigned to the shell variable b.

garethTheRed
  • 33,957
  • 1
    That's -vbenchmark="$benchmark" to assign the value of the shell variable (after expanding the \x sequences in it) to the awk variable. -vbenchmark=$benchmark without the quotes doesn't make any sense as that's invoking the shell's split+glob operator. – Stéphane Chazelas Dec 10 '14 at 11:12
  • 1
    @StéphaneChazelas - but the original author got away with it in this instance as a split & glob of 30 returns 30. Obviously he/she hadn't read your excellent QA on the subject :-) – garethTheRed Dec 10 '14 at 11:30
  • 2
    That's still invoking the split+glob operator which doesn't make sense. And it returns 30 unless IFS contains 3 or 0. For instance, if it's 0, that becomes awk -vbenchmark=3 '' '{thecode}' the files. The code becomes '' (which with most awk implementations make awk return immediately without an error); if it's 3, that becomes awk -vbenchmark= 0 '{the-code}' which will treat {the-code} as a file will cause awk to read that and the other files but output nothing as the code is now 0. – Stéphane Chazelas Dec 10 '14 at 11:42
  • @StéphaneChazelas - fair point. That'll teach me to try and argue... In my defence, I my answer was only commenting on the original code - I didn't write it. – garethTheRed Dec 10 '14 at 11:51