Exercise #2: Learning awk with Operators

by mike on February 13, 2011

In this example the search is for processes that are using 1.0% or more of the system memory. The operator “>=” is used to find that information.
awk '$4 >= 1' processes
root 14022 0.0 1.0 10012 2840 ? Ss Feb08 0:00 /usr/sbin/httpd
root 15857 0.0 1.1 10032 2900 ? Ss 12:02 0:00 sshd: root@pts/0

In the command you are also able to use comparisons so that you will create a range. In this example the system memory usage needs to be greater than 1% AND less than 1.2%. The “&&” mandates that if the first command is successful the second one will execute.

awk '$4 > 1 && $4 <= 1.2' processes
root 15857 0.0 1.1 10032 2900 ? Ss 12:02 0:00 sshd: root@pts/0

You can use awk to scan a field and have it match the text string you want. Here the “==” represents a match.
awk '$12 == Feb' processes
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 13901 0.0 0.4 7196 1056 ? Ss Feb08 0:00 /usr/sbin/sshd
root 14022 0.0 1.0 10012 2840 ? Ss Feb08 0:00 /usr/sbin/httpd
apache 14023 0.0 0.7 10012 2056 ? S Feb08 0:00 /usr/sbin/httpd
root 14031 0.0 0.4 4492 1104 ? Ss Feb08 0:00 crond
root 15864 0.0 0.5 3716 1500 pts/0 Ss 12:02 0:00 -bash

Locate one PID (Process ID) that is equivalent to a number.
awk '$2 ~ 14022' processes
root 14022 0.0 1.0 10012 2840 ? Ss Feb08 0:00 /usr/sbin/httpd

Expand that to create a range of process numbers. Note they are separated by the range separator “,”.
awk '$2 ~ 14022 , $2 ~ 14040' processes
root 14022 0.0 1.0 10012 2840 ? Ss Feb08 0:00 /usr/sbin/httpd
apache 14023 0.0 0.7 10012 2056 ? S Feb08 0:00 /usr/sbin/httpd
root 14031 0.0 0.4 4492 1104 ? Ss Feb08 0:00 crond
root 14039 0.0 0.2 5680 712 ? Ss Feb08 0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2
root 14040 0.0 0.1 5680 444 ? S Feb08 0:00 /usr/sbin/saslauthd -m /var/run/saslauthd -a pam -n 2

Here is another variation where the selection is a range found in field 2 but the print command only prints the first and eleventh fields.
awk '$2 ~ 14022 , $2 ~ 14040 {print $1,$11}' processes
root /usr/sbin/httpd
apache /usr/sbin/httpd
root crond
root /usr/sbin/saslauthd
root /usr/sbin/saslauthd

If you wanted to see what processes were opened by someone at the terminal you might try this but it would fail.
awk '$7 ~ pts/0' processes
awk: (FILENAME=processes FNR=1) fatal: division by zero attempted

You will need to include ” ” to make that work.

awk '$7 ~ "pts/0"' processes
root 15864 0.0 0.5 3716 1500 pts/0 Ss 12:02 0:00 -bash
root 15969 0.0 0.3 2536 908 pts/0 R+ 12:07 0:00 ps aux

{ 18 comments }

Vasilis February 13, 2011 at 10:27 am

Hey. I like your practical approach, but sometimes a little bit of “theory” could help..
Is there any difference between:
-awk ‘$7 ~ “pts/0″‘ procs
-and awk ‘$7 == “pts/0″‘ procs?

Thanks.

mike February 13, 2011 at 10:36 am

The relational operator “==” means equal to while the “~” tests to see if a field or variable matches a regex. Ultimately in this example the outcome is the same.

Vasilis February 13, 2011 at 11:25 am

Thanks :)

DetroitGeek February 13, 2011 at 2:37 pm

You’re making this too easy. I’m trying to figure out why I didn’t learn this years ago. Thank You :)

minimalist February 13, 2011 at 6:00 pm

Great tutorial! Keep it going!

abjr February 13, 2011 at 7:45 pm

Is it just my imagination or is the ‘==’ example wrong?

awk ‘$12 == Feb’ processes

There is no 12th field that equals Feb

mike February 13, 2011 at 8:33 pm

Your list of processes will be different of course, yes it works fine with the processes that I have here.

mike February 13, 2011 at 8:34 pm

You will have to consider that you will have a different list. Again this works fine with the list that I used.

Vinu Rajashekhar February 13, 2011 at 8:00 pm

awk ‘$12 == Feb’ processes

shouldn’t this be $9 instead of $12 ? Even after that the command doesn’t work for me, unless I change the command to

awk ‘$9 == “Feb13″‘ processes

mike February 13, 2011 at 8:38 pm

You may see different output depending on your version, are you using awk, nawk or gawk and what version.

Vinu Rajashekhar February 15, 2011 at 10:27 pm

I tried gawk 3.1.6 and original-awk 20071023, the awk used in “The AWK Programming Language”.

mike February 13, 2011 at 10:15 pm

The other difference is the ps command, I did these with ps aux, what are the options that you are using?

abjr February 14, 2011 at 5:12 am

But look at your results … even the first line doesn’t have 12 fields:

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND

COMMAND would be $11 … correct?

mike February 14, 2011 at 11:26 am

Use the field count.
awk ‘{print NF}’ processes
11
12
12
13
11
14
13
11
11
11
17
17
12
11
12

Vinu Rajashekhar February 15, 2011 at 10:25 pm

This is because the COMMAND column has spaces in between, like ps aux would be a command which will count as 2 fields. The position of the date field should never change from $9 though.

Marco February 14, 2011 at 6:10 am

CTRL+D

thanks again for this

Pepa February 14, 2011 at 12:59 pm

I think you need to clarify that what you call a “range separator”, the comma used between expressions, means that you select all the lines from the first line that matches the first expression until the next line that matches the second expression.

So: awk ‘$2 ~ 14022 , $1 ~ apache’ processes
Will return:
root 14022 0.0 1.0 10012 2840 ? Ss Feb08 0:00 /usr/sbin/httpd
apache 14023 0.0 0.7 10012 2056 ? S Feb08 0:00 /usr/sbin/httpd

(I comment because your example confused me; if it’s entirely clear to other people all the better!)

Vinu Rajashekhar February 15, 2011 at 10:29 pm

Yes, it confused me too, thanks for the clarification.

Comments on this entry are closed.

Previous post:

Next post: