Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Running a command from within a variable?

Status
Not open for further replies.

menski

Technical User
Oct 13, 2002
18
GB

Some languages allow you to put a command into a variable which will then run when the variable is called. eg:

print_field = "print $1' '$2' '$4"

might be put away at some point in a script and called later to output the contents of these fields.

It appears that this is not so in awk - unless somebody knows better!

dmk
 
You are right (g)awk does not offer one, but TWO ways to
do this ;)

First method:

print_field = $1" "$2" "$4
and,
:print_field | getline var
or for multiline output,
:while ((print_field | getline array[a++]) > 0)

Second Method:

print_field = $1" "$2" "$4
:system(print_field)


Also sprintf can be used to create your commands
sometimes more easily when dealing with returned,
array and static variables..

HTH
 
HTH - this looks good, thanks! I'll give them a whirl.

dmk
 
Unfortunately, this doesn't quite cut the mustard. The exact nature of the problem is that I have a script which I need to call with certain command line arguments giving (amongst other things) the search text + any files or directories to exclude. eg:

awktest -x /bin -x .bash_history -t chalk -t cheese

the routine for handling the command line switches then creates two variables:

exclude = "input_str == /\/bin/ || input_str == /.bash_history/"
text = "/chalk/ || /cheese/"

and will then be used as

if (exclude) {input_str = ""}

or

if (text) {do this; do that; do the other}

I have tried using sprintf:

if (sprintf(exclude)) {input_str = ""}

but without success. Am I missing something. Any help will (as usual) be gratefully received!

dmk
 
You will have great difficulty creating regexp's in this manner.
Better is to do something like:

function is_match(str,list, arr,a,x) {
#splitlist based on whitespace,breaks if whitespace in passed args
a = split(list,arr)
if (a) {
#iterate through all elements
for (x =1 ; x <= a ; x++) {
print &quot;Matching against:&quot;, arr[x], &quot;and&quot;, str
#match against each element
if (str ~ arr[x]) {
#return positive for a match
return 1
}
}
}
return 0
}


BEGIN {
#iterate through passed arguments
for (i=1 ; i <= ARGC ; i++) {
if (ARGV == &quot;-x&quot;) {
#build our restricted list by choosing &quot;-x&quot; + 1 in the array and concatenating with a whitespace sep.
restrict = length(restrict) < 1 ? ARGV[i + 1] :
restrict&quot; &quot;ARGV[i + 1]
}
if (ARGV == &quot;-t&quot;) {
#as above, for the excepted list
except = length(except) < 1 ? ARGV[i + 1] :
except&quot; &quot;ARGV[i + 1]
}
}
#verbose check
print &quot;RESTRICTED: &quot;,restrict, &quot;EXCEPTED: &quot;, except

#awk will complain and fail if you pass params as you
#try to main(). Instead all processing can be done here.
while ((getline < ARGV[ARGC - 1]) > 0) {
all_recs[p++] = $0
#load all lines in filename(last argument) - 1 toarray all_recs
}
close(ARGV[ARGC - 1])
#iterate through the array records matching against
#all records and expressions,actions are in the if blocks.
while(++t < p) {
if (is_match(all_recs[t],restrict)) {
input_str=&quot;&quot;
print &quot;Restrict match&quot;
}
if (is_match(all_recs[t],except)) {
print &quot;Except match&quot;
}
}
}

Now you can call the program like:
awk -f awkprog -t &quot;trueandfalse&quot; -x &quot;Thisisnottrue&quot; -x &quot;false&quot; -x &quot;notfalse&quot; -t &quot;truefalseandfalse&quot; scrap.txt

SAMPLE OP:
Matching against: Thisisnottrue and &quot;CAMEL_MODIFICATION&quot; = &quot;5F&quot;
Matching against: false and &quot;CAMEL_MODIFICATION&quot; = &quot;5F&quot;
Matching against: notfalse and &quot;CAMEL_MODIFICATION&quot; = &quot;5F&quot;
Matching against: trueandfalse and &quot;CAMEL_MODIFICATION&quot; = &quot;5F&quot;
Matching against: truefalseandfalse and &quot;CAMEL_MODIFICATION&quot; = &quot;5F&quot;
Matching against: Thisisnottrue and &quot;INTERNAL_CAUSE_AND_LOC&quot; = &quot;0003&quot;
Matching against: false and &quot;INTERNAL_CAUSE_AND_LOC&quot; = &quot;0003&quot;
Matching against: notfalse and &quot;INTERNAL_CAUSE_AND_LOC&quot; = &quot;0003&quot;
Matching against: trueandfalse and &quot;INTERNAL_CAUSE_AND_LOC&quot; = &quot;0003&quot;
Matching against: truefalseandfalse and &quot;INTERNAL_CAUSE_AND_LOC&quot; = &quot;0003&quot;
, etc...
 
Oh wow! Slightly more complicated than I hoped. Part of the problem is that the script is already very large. It is designed to take the result of

ls -aR1

convert it into a nice clean list, pump it through <file> to check which files are text files and then check these for the occurence of text strings (patterns).

At the moment it takes about 20 seconds to check the 3,500 odd files in my home directory; identify about 600 text files; read them and return some 3,500 lines which include the text. Speed then is of the essence.

I will test your suggestion and get back. Thanks!

dmk
 
marsd - sorry about the delay. The project is becoming embarassingly like a Swiss army knife - but your suggestions worked well. Thanks

dmk
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top