www.maxpagani.org
Home
CV
Blog
Photos
readings
downloads
work
links
F.A.Q.

interests
 travels
 trekking
 videogames
  working
  programming
  playing
 miniatures
 fitness
 programming
  C, C++
  Java
  Shell
  misc.

guestbook

mail

Shell Programming and Inserting a File into another one.


Having a blog is nice, but keeping inserting entries in the same html page (well, currently a bwt page) is boring and error prone. You have to find the right place to add the new entry, specify the title and the date caring of doing it in the same way you did before. Isn't it a good case for another shell script?

The goal is simple - take the title from the command line arguments, launch your favorite editor to read the blog article, insert the edited text below a marker in the blog page, adding title and date.

The decision about the marker is because I wanted some heading lines for the blog page (currently there is the classical 'Any comment?...').

The marker I choose is the (silly) HTML comment

<!-- blog STARTS below -->

Writing the structure of the script was quite simple, just checking the command line, launching the editor, checking wether the user has typed something... the difficult part was inserting the edited entry below the marker. The first attempt was to read the blog file line by line, searching for the marker line:

while read line
do
    if [ "${line/<!--*-->/}" != "$line" ]
    then
        # marker found
        echo "$line"
        echo
        echo "Inserting the new entry here"
    else
        echo "$line"
    fi
done

This works, but it could be really slow since every line is processed by the bash interpreter. Also I wasn't really comfortable with the variable expansion. I got no trouble testing with some particularly evil strings (containing dollars, quotes, backslashed), but in the past I was bitten too many times.
So I went on looking for a better solution. Head and tail commands must help in cases like this.

'head' prints the first 'n' lines of a file, while 'tail' prints the last 'n' lines of a file, but can be instructed to print from line 'n' onward.
The only missing detail is to find the line number where the marker is. Time for another dive in manpages-land. This seemed a good job for grep and in grep I found the answer - the -n flag prints the line number of the matching line in the form:

 lineNumber:matched line

It is simple to remove from ':' to the end of the line by using variable expansion. Finally adding a -m 1 (max count) to the grep command line you get online the 1st match.

Here is the loop above once rewritten with grep, head and tail -

    line=$(grep -m 1 -n '<!--.*-->' $1)
    line=${line%:*}
    head -$line $1 > $tempOut
    echo "" >> $tempOut
    echo "<B>$(date +"%Y-%m-%d %H:%M") - $2</B>." >> $tempOut
    cat $3 >> $tempOut
    tail +$(($line+1)) $1 >>$tempOut

Conclusions

When scripting with bash the traditional programming approach with loops, structures and so on may not be the simplest/best performing solution. The script shoudl be used as a glue to connect together existing special purpouse commands.

Also notice that I have violated the law about 'premature optimization' since I had no proof about performance issue. Luckly, for that the resulting solution is simpler, I can call the KISS principle to aid.

Massimiliano Pagani


created with vim   Valid HTML 4.01! This page has been visited times
This site and its content is (C) by Massimiliano Pagani
Last modified 2008/05/12 13:52:29