Introduction
Announcements

Schedule
Labs
Assignments
TA office hours

Tests, exam

Topic videos
Some course notes
Extra problems
Lecture recordings

Discussion board

Grades so far

1. [8 marks]
Each subpart of this question builds upon the previous. If you can't get part of the question, you can write things like "part 'a' answer goes here".

a) Write a regular expression which matches "any positive integer".

Solution:

0*[1-9][0-9]*

We will accept [1-9][0-9]* for the mark. In fact, we will also accept [0-9][0-9]* for the mark, although that will also match "0", which is not a positive integer. I would have written the problem as "any non-negative integer" except that I thought that that terminology might confuse and that wasn't the point for this test.

But "[1-9][0-9]*" doesn't include things like "003", which, while oddly-written, is certainly a positive integer. So I believe that the correct answer is 0*[1-9][0-9]*.


b) "grep -v" outputs lines which do not match the given pattern. Remembering "^" for beginning of line and "$" for end of line, write shell commands to check whether the file "abc" contains just one integer per line (and nothing else). Output "yes" (only integer lines) or "no" (at least one inappropriate line).

Solution:

if grep -v '^0*[1-9][0-9]*$' abc >/dev/null
then
    echo no
else
    echo yes
fi


c) Write a complete shell script which takes exactly one file name as command-line argument and outputs the sum of all of the numbers in that file, if the file contains only integers and one per line; or outputs a suitable error message if the file contains anything else. You also have to check the argument count and output an appropriate usage message, and otherwise behave like a proper complete shell script. (You can, however, assume that the addition never overflows what expr can do.)

Solution:

PATH=/bin:/usr/bin
if test $# -ne 1
then
    echo usage: $0 file >&2
    exit 1
fi
if grep -v '^0*[1-9][0-9]*$' "$1" >/dev/null
then
    echo "$1": file does not contain solely integers, one per line >&2
    exit 1
fi
sum=0
while read i
do
    sum='expr $sum + $i'
done <"$1"
echo $sum
... or instead of "while read i ...", you could do:
for i in `cat "$1"`
...
This 'for' version would be problematic if the lines contained white space, but we know at this point that they don't.


[sample midterm from Fall 2011]