Exercises for Friday, October 8, 2004 In class last Friday, I told you that most web pages on web servers are written in HTML. This statement was once true but is no longer. Today, most web pages are generated by running scripts on the web server; these scripts construct HTML (or XHTML) files (referred to as 'dynamic content') on the fly and then send them on to the client. The scripts are written in any number of languages including the shell scripting language that we've been working in, Perl - a language that is somewhere between our shell language and C, Python - a recently introduced language designed for much the same range of applications as Perl, PHP - a language designed from the ground up for dynamically generating web content, and even Scheme - a dialect of Lisp that was introduced in Chapter 1 and we'll see in later in the course. In this exercise, you'll write a script that takes as input a table consisting of database records generated by an SQL query and produces as output an HTML file featuring an HTML table in which the rows are the records and the columns are the fields in the database table. We'll assume that the database table is formatted as we did in our database exercise: lines are records and the fields are separated using semicolons at delimiters. You'll need to know a little more HTML to carry out this exercise. Save the following HTML code to a file named 'table.html' and then open it using a browser. Title
Table Caption
COLUMN 1 COLUMN 2
ROW 1 DATUM 1,1 DATUM 1,2
ROW 2 DATUM 2,1 DATUM 2,2
ROW 3 DATUM 3,1 DATUM 3,2
The 'table' tag takes many more options than shown but the two shown are pretty common: 'align' can be 'right', 'left' or 'center' and 'border' is an integer greater than or equal to zero. The 'tr' tag inside a 'table' environment is used to specify a row of data, the 'td' and 'th' are used to display the data for a cell (or box) in the table with the 'th' form typically reserved for row or column labels (in most browsers the 'th' form is displayed in a bold face type). Experiment with 'table.html' by adding rows and columns and altering the alignment. You can set the alignment in rows or cells using the same syntax as shown for the 'table' tag; alignment specifications in a 'table' tag refer to the alignment of the table on the page while alignment specifications in 'tr', 'th' and 'td' tags determine the arrangement of text in cells. 1. Create a table with columns 'First', 'Last', 'Age' and 'Gender'. Populate the table with 3 rows of fake data. The column headers should be in bold faced type and centered in their cells, the first and last names should be left justified, ages should be right justified and gender identifiers ('M' or 'F') should be centered in the gender column. 2. Write a script that reads from the standard input the result of a SQL query and produces as output an HTML document that features an HTML table displaying display the query. For this exercise, the result of the SQL query is assumed to have one record per line with fields delimited by semicolons. For this exercise, you need not label the columns or rows. Here's an example of the sort of input your script should be able to handle: % cat employee Carla;Carbuncle;21;F Nathan;Normal;33;M Alice;Altavista;23;F Ernest;Sequitur;26;M In writing this script, it would be nice if you could go through the file line by line just like the 'awk', 'grep' and 'sed' utilities do. Fortunately, the C-shell scripting language provides just such an option: '$<' substitutes a line from the standard input, with no further interpretation. ('$<' is also useful to read from the keyboard in a shell script; check out 'Advanced Topics' (topic #3) in ../../../docs/scripts.txt for an example of an interactive script that implements a simple guessing game.) % cat number #!/bin/csh set line = $< set n = 1 while ( "$line" != "" ) foreach word ( $line ) printf "$n - $word\n" end set line = $< @ n ++ end % cat employee | number cat employee | number 1 - Carla;Carbuncle;21;F 2 - Nathan;Normal;33;M 3 - Alice;Altavista;23;F 4 - Ernest;Sequitur;26;M That's a start, but how do you read the individual fields in each record? As a hint, try replacing 'foreach word ( $line )' with 'foreach word ( `echo $line | tr ";" " "` )'. This doesn't quite work because, as you might recall, we used the semicolon as a delimiter precisely because if we used the space character as a field separator we would not be able to distinguish spaces separating words within an individual field from those separating distinct fields. Judicious use of 'sed' will fix this however. Once you understand how to break up the input into records (lines) and fields (sequences of words separated by semicolons), the only tricky part left involves writing one loop nested inside a second loop to construct the table. The outer loop reads in a line from the standard input and produces the required 'tr' (row) tags, while the inner loop breaks up the line into words and produces the requisite 'th' (column) tags and associated text. 3. Rewrite your solution to Exercise 2 but this time assume that the first two lines of the input file include the names of the fields and alignment type for displaying the data in each column. The resulting HTML file should display the field names at the top of each column and format the data accordingly. % cat employee First;Last;Age;Gender LEFT;LEFT;RIGHT;CENTER Carla;Carbuncle;21;F Nathan;Normal;33;M Alice;Altavista;23;F Ernest;Sequitur;26;M 4. Rewrite your solution to Exercise 3 to take two optional arguments. If a second argument appears on the command line it is assumed to be a string intended for use as the title of the HTML page. If a third argument appears on the command line, it is assumed to be a string intended for use as the caption of the HTML table. 5. Rewrite your solution to Exercise 4 to support two command-line options. Command-line options can be handled in shell scripts just as you would handle any argument; typically the script scans 'argv' to extract options from the rest of the command line arguments, assigning variables and performing additional computations as appropriate to carry out the options as specified. Use this alternative directive as the first line of your script: #!/bin/csh -b The '-b' option to the C-shell forces a 'break' from option processing, causing any further shell arguments to be treated as non-option arguments. The remaining arguments will not be interpreted as shell options. This is used to pass options to a shell script without employing convoluted text processing. % cat options #!/bin/csh -b foreach word ( $argv ) if ( "$word" == "-u" ) echo "dash ewe" if ( "$word" == "-l" ) echo "dash ell" end % options -l misc -u misc misc dash ell dash ewe Use the '-d' option to specify an alternative delimiter. Your script should use the space character as the default delimiter if no '-d' option is specified. Use the '-a' option to indicate that the line encoding the alignment directives is present. If the '-a' option is not present on the command line, you should assume that the line specifying alignment directives is not present in the input. 6. Figure out a way to use the script that you wrote for Exercise 5 in conjunction with the scripts that we wrote in the database exercise to produce nicely formatted output. (Think about how you might invoke a browser in a script to display query results.)