Solutions for the exercises for Friday, October 8, 2004
2. Solution for Exercise 2:
#!/bin/csh
# This script reads from the standard input the result of
# an SQL query and produces as output an HTML document that
# features an HTML table displaying the query. The result
# of the SQL query is assumed to have one record per line
# with the record fields delimited by semicolons.
# begin the HTML document
echo ""
# begin the body of the document
echo "
"
# begin the table used to display the data
echo ''
# read from the standard input record by record
set line = $<
while ( $line != "" )
# begin a new row and the first field in that row
printf "\n "
# pad the semicolon with spaces to form a distinct word
foreach word ( `echo $line | sed 's/;/ ; /g'` )
# if you encounter a field separator
if ( $word == ";" ) then
# end the current field and start a new one
printf " | \n "
else
# otherwise print each word in the current field
printf "$word "
endif
end
# end the last field in the current row and the current row
printf " | \n
\n"
# read another record from the standard input
set line = $<
end
# end the table
echo "
"
# end the body of the document
echo ""
# end the HTML document
echo ""
3-5. A combined solution to Exercises 3-5. This solution doesn't
work for delimiters corresponding to white space but otherwise
works fine for single-character delimiters that aren't meta
characters in the 'sed' utility's regular expression language.
% cat file | table.options -c "Table Caption" -a -t "Document Title" -d ";"
...
...
% cat table.options
#!/bin/csh -b
# table command - table [-d delimiter] [-a] [-t title] [-c caption]
# This script reads from the standard input the result of an SQL query
# and produces as output an HTML document that features an HTML table
# displaying the query. The script also accepts several options that
# can appear in any order on the command line. The input is assumed
# to have one record per line with fields separated by a
# single-character delimiter. The first line of the file is assumed
# to contain the names of the fields. The '-a' signals that the
# second line in the input specifies a sequence of alignment
# directives ('left', 'right' or 'center') for displaying the
# corresponding fields. The '-c' option signals a string intended for
# use as the caption of the HTML table. The default delimiter is the
# space character. The '-d' option is used to specify an alternative
# to the default delimiter. The '-t' option signals a string intended
# for use as the title of the HTML document.
# process the command-line options
while ( $#argv > 0 )
switch ( $argv[1] )
case "-a":
shift argv
set alignment
breaksw
case "-c":
shift argv
set caption = ( $argv[1] )
shift argv
breaksw
case "-d":
shift argv
set delimiter = $argv[1]
shift argv
breaksw
case "-t":
shift argv
set title = ( $argv[1] )
shift argv
breaksw
default:
shift argv
endsw
end
# if the '-d' option is not present then set the default delimiter
if ( ! $?delimiter ) then
# the default is semicolon; can't deal with white space delimiters
set delimiter = ";"
endif
# the first line of input is assumed to consist of column headers
set headers = ( `echo $< | sed 's/'$delimiter'/ '$delimiter' /g'` )
# if the '-a' option is present on the command line then the
# second line of the input consists of alignment directives
if ( $?alignment ) then
# we exploit fact that alignment directives are single words
set alignment = ( `echo $< | sed 's/'$delimiter'/ /g'` )
else
# if '-a' option is not present all fields are center aligned
# the number of fields is half of one plus length of $headers
@ n = ( $#headers + 1 ) / 2
# we use a trick to create a list of alignments of this length
set alignment = ( `repeat $n echo center` )
endif
# begin the HTML document
echo ""
# insert the title if present
if ( $?title ) then
printf "\n"
foreach word ( $title )
printf "$word "
end
printf "\n\n"
endif
# begin the body of the document
echo ""
# begin the table used to display the data
echo ''
# insert the caption if present
if ( $?caption ) then
printf ""
foreach word ( $caption )
printf "$word "
end
printf "\n"
endif
# begin the top row of headers
printf "\n "
# insert the name of each field
foreach word ( $headers )
if ( $word == "$delimiter" ) then
printf " | \n "
else
printf "$word "
endif
end
# end the header and the top row
printf " | \n
\n"
# read from the standard input record by record
set line = $<
while ( $line != "" )
# initialize the counter used to insert alignments
set rcrd = 1
# begin a new row and the first field in that row
printf '\n '
# pad the semicolon with spaces to form distinct words
foreach word ( `echo $line | sed 's/'$delimiter'/ '$delimiter' /g'` )
if ( $word == "$delimiter" ) then
# increment the counter used to insert alignments
@ rcrd ++
# end the current field and start a new one
printf ' | \n '
else
# print each word of the current field in turn
printf "$word "
endif
end
# end last field in current row and then end the row
printf " | \n
\n"
# read another record from the standard input
set line = $<
end
# end the table
echo "
"
# end the body of the document
echo ""
# end the HTML document
echo ""