Unix Shell - Using eval with awk

This is Interesting: Free IT Magazines  
Home > Archive > Unix Shell > February 2007 > Using eval with awk





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Using eval with awk
maxshop

2007-02-23, 1:18 pm

Environment: AIX 5.2 (ksh)

Hello Group,

I am trying to use eval with awk, but somehow I just cannot get it
right. Maybe some of you can point me in the right direction. Here is
what I am doing inside a script:

#!/usr/bin/ksh

loginname=$1
excl_users="root"

If [[ ! -z $loginname ]]
then
cond1="\$1 == lname &&"
var1="lname=\$loginname"
fi

# My original command looked something like this:
ps -ef | awk '$0 ~ /_oracle/ print {$1,$2,$3,$6}' | egrep -vw
"$excl_users" | sort -u > /tmp/test.log

# I would now like to include $cond1 and $var1 --- So, if $loginname
contains a value, the ps
# command will return processes for that user only that contain
"_oracle". If it does not contain
# a value, then it should return all processes that contain "_oracle".

# I know that the following does not work & that's where I need some
help.

eval 'ps -ef | awk '$cond1 $0 ~ /_oracle/ print {$1,$2,$3,$6}' $var1 |
egrep -vw "$excl_users" | \
sort -u > /tmp/test.log'

Thanks for any suggestions.
S

Ed Morton

2007-02-23, 1:18 pm

maxshop wrote:
> Environment: AIX 5.2 (ksh)
>
> Hello Group,
>
> I am trying to use eval with awk, but somehow I just cannot get it
> right. Maybe some of you can point me in the right direction. Here is
> what I am doing inside a script:
>
> #!/usr/bin/ksh
>
> loginname=$1
> excl_users="root"
>
> If [[ ! -z $loginname ]]


ITYM:

if [ -n "$loginname" ]

> then
> cond1="\$1 == lname &&"
> var1="lname=\$loginname"
> fi
>
> # My original command looked something like this:
> ps -ef | awk '$0 ~ /_oracle/ print {$1,$2,$3,$6}' | egrep -vw
> "$excl_users" | sort -u > /tmp/test.log
>
> # I would now like to include $cond1 and $var1 --- So, if $loginname
> contains a value, the ps
> # command will return processes for that user only that contain
> "_oracle". If it does not contain
> # a value, then it should return all processes that contain "_oracle".
>
> # I know that the following does not work & that's where I need some
> help.
>
> eval 'ps -ef | awk '$cond1 $0 ~ /_oracle/ print {$1,$2,$3,$6}' $var1 |
> egrep -vw "$excl_users" | \
> sort -u > /tmp/test.log'
>
> Thanks for any suggestions.
> S
>


awk is not shell. You cannot access shell variables in awk any more than
you can access shell variables in C. You CAN jump out of awk back into
shell by nesting single quotes, e.g.:

awk 'awk stuff...'shell stuff...'more awk stuff' file

but that's very risky as it leads to bizarre errors and equally bizarre
error messages if the "shell stuff..." contains unexpected text.

You can also initialise an awk variable to the value of a shell
variable. That's the safer, preferred way to do it. See question 24 in
the FAQ (http://home.comcast.net/~j.p.h/cus-faq-2.html#24) for a
discussion on that. The downside for you is that you can't pass the
actual condition (e.g. "==" in "cond1="\$1 == lname") but that's really
messay anyway.

I'd write what you appear to be trying to do with:

if ...
cond1="\$1 == lname &&"
var1="lname=\$loginname"
fi
.... | awk '$cond1 $0 ~ /_oracle/ print {$1,$2,$3,$6}' $var1

as just this:

.... | awk -v lname="$loginname" '/_oracle/ && (!lname || ($1 == lname)){
print $1,$2,$3,$6 }'

Regards,

Ed.
maxshop

2007-02-23, 1:18 pm


> as just this:
>
> ... | awk -v lname="$loginname" '/_oracle/ && (!lname || ($1 == lname)){
> print $1,$2,$3,$6 }'
>
> Regards,
>
> Ed


Thanks Ed, that worked!

aryzhov@spasu.net

2007-02-23, 1:18 pm

Firstly, the curly bracket in awk print action is in the wrong
position.
Hence the awk syntax error.

Then, you really have to be careful with the quotes and $ signs.
Especially when using a quoted expression inside another one.
Usually, the inside quotes need to be preceded with an escape
character \'
or duplicated.
I also have an irrational feeling that double qoutes " behave more
predictably in nested quote expressions than single quotes '

I suggest to use "eval echo" for debugging.

This one should be slighly closer to what you are trying to achieve:
eval "ps -ef | awk '\"\$cond1\" \$0 ~ /_oracle/ {print \$1,\$2,\$3,\
$6}' \$var1 | egrep -v \"\$excl_users\" | sort -u > /tmp/test.log"

Regards,
Andrei

Ed Morton

2007-02-23, 1:18 pm

maxshop wrote:
>
>
> Thanks Ed, that worked!
>


Good, now on to your second issue:

excl_users="root"
ps -ef | awk '...' | egrep -vw "$excl_users"

You don't need to use awk AND grep since awk can do pattern
matching/exclusion just as easily as grep can. It looks like what you're
trying to do is only produce output for users other than "root", so just
change this:

excl_users="root"
ps -ef | awk -v lname="$loginname" '/_oracle/ && (!lname || ($1 ==
lname)){ print $1,$2,$3,$6 }' | egrep -vw "$excl_users"

to this:

ps -ef | awk -v lname="$loginname" '/_oracle/ && ($1 != "root") &&
(!lname || ($1 == lname)) { print $1,$2,$3,$6 }'

Regards,

Ed.
maxshop

2007-02-23, 1:18 pm

> Good, now on to your second issue:
>
> excl_users="root"
> ps -ef | awk '...' | egrep -vw "$excl_users"
>
> You don't need to use awk AND grep since awk can do pattern
> matching/exclusion just as easily as grep can. It looks like what you're
> trying to do is only produce output for users other than "root", so just
> change this:
>
> excl_users="root"
> ps -ef | awk -v lname="$loginname" '/_oracle/ && (!lname || ($1 ==
> lname)){ print $1,$2,$3,$6 }' | egrep -vw "$excl_users"
>
> to this:
>
> ps -ef | awk -v lname="$loginname" '/_oracle/ && ($1 != "root") &&
> (!lname || ($1 == lname)) { print $1,$2,$3,$6 }'
>
> Regards,
>
> Ed.


Ok, will do it this way.

One other question: Apart from searching for processes that contain
"_oracle", I am also searching for the db name. The db name could
appear anywhere under the CMD column of the ps command & could have
any of the following forms:

xx xxx master xx xxx
xx xxx /data/db/master xx xxx
xx master.db xxx xx xxx
xx xxx /data/db/master.db xx xxx

The "xx xxx" denotes that there are a bunch of parameter/arguments
which could appear anywhere in the CMD column. Is there a way to just
search for processes that contain "master" or "master.db"?

The current command that I have is something like this: I know this
will fail if there is a process out there that would contain
master.prf (for example)

DB_NAME=master
ps -ef | awk '/_oracle/ && $0 ~ db_name {print $1,$2,$3,$6}'
db_name="$DB_NAME"

Thanks,
S

Ed Morton

2007-02-23, 7:17 pm

maxshop wrote:
>
>
> Ok, will do it this way.
>
> One other question: Apart from searching for processes that contain
> "_oracle", I am also searching for the db name. The db name could
> appear anywhere under the CMD column of the ps command & could have
> any of the following forms:
>
> xx xxx master xx xxx
> xx xxx /data/db/master xx xxx
> xx master.db xxx xx xxx
> xx xxx /data/db/master.db xx xxx
>
> The "xx xxx" denotes that there are a bunch of parameter/arguments
> which could appear anywhere in the CMD column. Is there a way to just
> search for processes that contain "master" or "master.db"?
>
> The current command that I have is something like this: I know this
> will fail if there is a process out there that would contain
> master.prf (for example)
>
> DB_NAME=master
> ps -ef | awk '/_oracle/ && $0 ~ db_name {print $1,$2,$3,$6}'
> db_name="$DB_NAME"


DB_NAME="^master(.db)?$"
ps -ef | awk -v db_name="$DB_NAME" '/_oracle/ && $0 ~ db_name {print
$1,$2,$3,$6}'

Using "-v" is a good habit to get into for the reasons specified in the
FAQ I mentioned earlier in the thread.

Regards,

Ed.
Ed Morton

2007-02-23, 7:17 pm

Ed Morton wrote:

> maxshop wrote:
>
>
>
> DB_NAME="^master(.db)?$"


Make that:

DB_NAME="[ /]master(.db)?[ ]"

If a blank character isn't adequate, make it:

DB_NAME="[[:space:]/]master(.db)?[[:space:]]"

> ps -ef | awk -v db_name="$DB_NAME" '/_oracle/ && $0 ~ db_name {print
> $1,$2,$3,$6}'
>
> Using "-v" is a good habit to get into for the reasons specified in the
> FAQ I mentioned earlier in the thread.
>
> Regards,
>
> Ed.

Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2009 webservertalk.com