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.
2 Answers 2
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 ..
-
That is,
benchmark=30;grep "Waiting for timer" wk.txt | awk -vbenchmark=$benchmark '6ドル > benchmark' | wc -l
is the same asgrep "Waiting for timer" wk.txt | awk -v threshold=30 '6ドル'
, which is not returning anything other than a simplegrep "Waiting for timer" wk.txt
for me. Strange.Sreeraj– Sreeraj2014年12月10日 10:51:00 +00:00Commented Dec 10, 2014 at 10:51 -
@Sree Well, your input data might be such. The awk code is checking if
6ドル
is greater than the assigned value ofbenchmark
, and your example case has6ドル > 30
. (Any string starting with alphabets will be greater than "30", (or a any string composed only of digits).)muru– muru2014年12月10日 10:55:28 +00:00Commented Dec 10, 2014 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– Sreeraj2014年12月10日 11:35:41 +00:00Commented Dec 10, 2014 at 11:35
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
.
-
1That'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– Stéphane Chazelas2014年12月10日 11:12:58 +00:00Commented Dec 10, 2014 at 11:12 -
1@StéphaneChazelas - but the original author got away with it in this instance as a split & glob of
30
returns30
. Obviously he/she hadn't read your excellent QA on the subject :-)garethTheRed– garethTheRed2014年12月10日 11:30:12 +00:00Commented Dec 10, 2014 at 11:30 -
2That'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 becomesawk -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 now0
.Stéphane Chazelas– Stéphane Chazelas2014年12月10日 11:42:04 +00:00Commented Dec 10, 2014 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– garethTheRed2014年12月10日 11:51:30 +00:00Commented Dec 10, 2014 at 11:51
b=$(awk -vbenchmark='30' '/Waiting for timer/&&6ドル>benchmark{x++}END{print x}' wk.txt)
or if you didn't wnat a pointless variableb=$(awk '/Waiting for timer/&&6ドル>30{x++}END{print x}' wk.txt)