February 14, 2008

command line quizzes part 2

Here's part two of the command line quizzes. Part one can be found here.
Q: Given that "top -b -n 1" gives the following output, write a script which kills all processes that use more than 25% of the processing power.


Tasks: 85 total, 1 running, 84 sleeping, 0 stopped, 0 zombie
Cpu(s): 4.7%us, 0.6%sy, 0.0%ni, 93.7%id, 0.8%wa, 0.2%hi, 0.1%si, 0.0%st
Mem: 506372k total, 495416k used, 10956k free, 12364k buffers
Swap: 0k total, 0k used, 0k free, 195588k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6159 root 19 -1 357m 38m 5380 S 2.0 7.9 7:02.21 X
6271 mats 20 0 123m 38m 25m S 2.0 7.8 1:33.09 amarokapp
6287 mats 20 0 25840 9916 7324 S 2.0 2.0 0:29.45 gkrellm
1 root 20 0 1612 544 472 S 0.0 0.1 0:00.84 init
2 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 kthreadd
3 root RT -5 0 0 0 S 0.0 0.0 0:00.00 migration/0
4 root 15 -5 0 0 0 S 0.0 0.0 0:02.08 ksoftirqd/0
5 root RT -5 0 0 0 S 0.0 0.0 0:00.00 watchdog/0
6 root 15 -5 0 0 0 S 0.0 0.0 0:00.16 events/0
7 root 15 -5 0 0 0 S 0.0 0.0 0:00.00 khelper
42 root 15 -5 0 0 0 S 0.0 0.0 0:00.11 kblockd/0

Here's a solution.

#!/bin/bash
#script to kill all processes which use more than 25% of the cpu
top -b -n 1 | awk 'NR >= 8 && $9 > 25 {print $1}' | xargs -r kill

Thanks to Ralph for this solution.


Q: Given the following two CSS files, write a script to verify that every class is only defined once (catch duplicate declarations).

File 1: first.css

body {font-family:Verdana;}
.header {font-size:90%; }
.article {line-height:1.1em;}
.footer {font-size:80%; }
.main .left #contents {float:left;}

File 2: second.css

#article .title {font-size:110%;}
.header {font-weight:bold;}
.email {font-family:Courier;}
.address {line-height:0.8em;}
.left {text-align:left;}

Here's a solution.

#!/bin/bash
#script to find out if two css files contain the same class name

#Use sed to filter out the css rules and put all the ids and classes on their own line
#Use sed again to only keep the class names
#Use sort and uniq to figure out the dups
classnames=$(sed -e 's/\([^{]*\).*/\1/g' -e 's/ /\n/g' $@ | sed -n -e '/\.\w\+/ p' | sort | uniq -dc | sort -r)
echo -e "\nDuplicate classes:\n"
echo "$classnames"
echo -e "\nGrepped files:\n"
#grep the files in argument for the class names found above
grep --color -n "$(echo "$classnames" | awk '{print $2}' | sed -e 's/\./\\./g' -e 's/\n/\|/g')" $@

It can be called like so.
./dupcss.sh first.css second.css

And gives the following output.
Duplicate classes:

2 .left
2 .header

Grepped files:

first.css:2:.header {font-size:90%;}
first.css:5:.main .left #contents {float:left;}
second.css:2:.header {font-weight:bold;}
second.css:5:.left {text-align:left;}

Grepping the files and displaying the results is just a convenience to the user.


I don't have any other quizzes on the back burner but I do have a few good links:

5 comments:

Ralph said...

For the first one,

top -b -n 1 | awk 'NR >= 8 && $9 > 25 {print $1}' | xargs -r kill

Why do you use xargs? It's doing nothing useful in your version. Idiomatic awk scripts make use of the `pattern action' style of programming. tail was redundant given it was being used to skip lines at the start and awk can do that simply. xargs's -r option stops kill from given the usage message.

mats said...

You're absolutely right. I changed the main post with your version.

Ralph said...

I don't know CSS-syntax precisely but here's a stab based on stripping everything after the open brace.

$ classnames() { sed 's/{.*//; y/ /\n/' "$@" | grep '^\.' | sort -u; }
$ classnames <first.css
.article
.footer
.header
.left
.main
$

$ cmp -s <(classnames first.css) <(classnames first.css) || echo they differ
$ cmp -s <(classnames first.css) <(classnames second.css) || echo they differ
they differ
$

The question was if the two define the same classes. The same class being defined more than once in the same file is presumably not a problem but I think the original will treat it as an error.

Cheers, Ralph Corderoy.

mats said...

Hey Ralph,
The idea is to find out if a class is defined in multiple places. I think your solution would almost always say the two files differ, which isn't helpful. Of course the wording of the question was ambiguous so I changed it.

Also, it's hard to know whether or not defining a class twice in the same file is a mistake. Sometimes it is, sometimes it's not, which is why I grep the files and display the results so the user knows where were the duplicates.

Ralph said...

Hi mats, you're right, I shouldn't have been checking to see they define the same set.

So I'd change the "cmp -s" for "comm -12", drop the "|| echo..." bit, and leave everything else the same. That will list those that are duplicates.

Cheers, Ralph Corderoy.