It's a fairly odd thing to do, dynamic case statement generation...but yes, it's possible.
I would do it something like as follows (if I had explored all other approaches I could think of; I don't know that I would recommend this):
. <( awk -F= 'BEGIN { print "case \"$line\" in" }
{ print $1 ") ret=" $2 ";;" }
END { print "esac" }' patternfile )
If patternfile
contains
pattern1=result1
pattern2=result2
pattern3=result3
the awk
command by itself would output
case "$line" in
pattern1) ret=result1;;
pattern2) ret=result2;;
pattern3) ret=result3;;
esac
and with the . <( awk ... )
construct this will be sourced into your script just as though you had written the case switch directly in your script file.
That answers "dynamic case statement creation" in a shell script. However, since you're planning on doing this within a loop, the above would be a very bad way to do it—since you would run awk
10,000 times on your patternfile
, thus outweighing any possible performance benefit.
Instead it would be better to write the code generator to create a case switch within a function definition—create and source a whole function definition, in other words:
# At the top of your script file:
. <( awk -F= 'BEGIN { print "my_case_switch_function() {"
print "case \"$1\" in" }
{ print $1 ") ret=" $2 ";;" }
END { print "esac"
print "}" }' patternfile )
# Within your while loop (or wherever else you want):
my_case_switch_function "$line"
This would allow you to re-use the generated case
switch over and over (10,000 times if you like) after only processing patternfile
once. So the performance is as good as you would get if you manually created the case switch from the patternfile
and hard-coded it in your script (except for the small overhead of running awk
once on a 150 line file, which is negligible next to processing 10,000 lines).
However, it must be reiterated: shell script case switches are not the tool for processing a 10,000 line file line by line. So even though this solution closely approaches the performance you could get with a hardcoded case switch, it will probably still be slow.
To quote Stephane Chazelas:
As said earlier, running one command has a cost. A huge cost if that command is not builtin, but even if they are builtin, the cost is big.
And shells have not been designed to run like that, they have no pretension to being performant programming languages. They are not, they're just command line interpreters. So, little optimisation has been done on this front.
awk
.)awk
rather than a shell case switch—see Why is using a shell loop to process text considered bad practice?. (2) If the list of patterns doesn't change very often, write a code generator to accept the pattern list and output anawk
script with the patterns hard-coded. This is very likely the most efficient given the numbers of lines you mention.result1
,result2
, etc.?