Tuesday, November 21, 2006

Hyperlink "cal" in MediaWiki

I used to provide hyperlink to the dates as a unordered list and users have to do a lot of scrolling in order to locate the actual date.

In UNIX, "cal" provides a calendar output per year with 3 months in a row. The below script is to convert the plain text output of "cal" to MediaWiki hyperlink format. For the Lottery Intelligence case, the dates need to be hyperlinked are Sunday, Wednesday and Saturday.

#! /bin/sh

yr=${1:-`date '+%Y'`}
for i in 1 2 3 4 5 6 7 8 9 10 11 12
do
  cal $i $yr | awk '{printf("%-21s\n",$0)}' |   sed   -e 's/ 1 /01 /' -e 's/ 2 /02 /' -e 's/ 3 /03 /' -e 's/ 4 /04 /'   -e 's/ 5 /05 /' -e 's/ 6 /06 /' -e 's/ 7 /07 /' -e 's/ 8 /08 /'   -e 's/ 9 /09 /' |   nawk -v yr=$yr -v mth=$i 'NR<=2{printf("%s\n",$0)} NR>=3{
    sun=substr($0,1,2)
    if (sun!="  ") {
      sun=sprintf("[[%s-%02d-%s|%s]]",yr,mth,sun,sun)
    }
    mon=substr($0,4,2)
    tue=substr($0,7,2)
    wed=substr($0,10,2)
    if (wed!="  ") {
      wed=sprintf("[[%s-%02d-%s|%s]]",yr,mth,wed,wed)
    }
    thu=substr($0,13,2)
    fri=substr($0,16,2)
    sat=substr($0,19,2)
    if (sat!="  ") {
      sat=sprintf("[[%s-%02d-%s|%s]]",yr,mth,sat,sat)
    }
    printf(" %s %s %s %s %s %s %s\n",sun,mon,tue,wed,thu,fri,sat)
  }' > $i.$yr
done


(paste 1.$yr 2.$yr 3.$yr; echo " "; paste 4.$yr 5.$yr 6.$yr; echo " "; paste 7.$yr 8.$yr 9.$yr; echo " "; paste 10.$yr 11.$yr 12.$yr) | sed -e 's/  /  /g' > $yr


for i in 1 2 3 4 5 6 7 8 9 10 11 12
do
  rm -f $i.$yr
done

Labels: , ,

Sunday, November 05, 2006

Better Script

On 1 Nov 2006, Linux Journal Weekly Newsletter posted the following script.
 THE BRAIN TRUST: READERS SHARE THEIR EXPERTISE

   Thanks to Josmar in (I'm totally jealous) Paraná, Brazil for this tip:

   Writing a CGI module entirely in BASH is a lot of fun. When, however, you
   have to find something in a certain file and render just some of the fields
   in an HTML table, this little trick always helps.

   Lets say you have something like this expense report in a file named
   "expenses.txt":

      John, lunch, 3.50, Apr/01/2006
      Karen, dinner, 8.00, May/30/2006
      John, parking, 1.00, May/30/2006
      Peter, dinner, 4.00, Apr/02/2006
      Karen, lunch, 6.00, May/30/2006

   And you need to render a HTML table for Karen's expenses, like this one:

         Date      Cost  Description
      May/30/2006  8.00    dinner
      May/30/2006  6.00    lunch

      Total Karen's expenses: 14.00

   This script converts the "expenses.txt' file into the HTML you need to
   produce the table above.

      #!/bin/bash
      PERSON="Karen"
      grep -iF "$PERSON" expenses.txt | cut -f 2-4 -d , | tr -d ',' > /tmp/exp1.$$
      if [ -s /tmp/exp1.$$ ]; then
         TOTAL=0
         echo "<table border=\"1\"><tr><th>Date</th><th>Cost</th><th>Description</th></tr>"
         for I in `cat /tmp/exp1.$$ | tr ' ' '_' `; do
         echo "$I" | tr '_' ' ' > /tmp/exp2.$$
         read DESCR COST DATE < /tmp/exp2.$$
         echo "<tr><td>$DATE</td><td>$COST</td><td>$DESCR</td></tr>"
         TOTAL=`echo "$TOTAL+$COST" | bc`
         done
         echo "</table><p>Total $PERSON's expenses: $TOTAL</p>"
      else
         echo "No data for '$PERSON'"
      fi
      rm /tmp/exp1.$$ /tmp/exp2.$$

   You can also use this script as a basic template for creating scipts to
   convert CSV (comma separated values) files into HTML tables. Most databases
   and spreadsheets can export data directly into CSV files.

   Thanks to everyone for your tips! Please send more of them to share with our
   community of readers! My email is jgray@ssc.com. We'll send you a free
   t-shirt for your efforts (or a penguin chair for the best one)! Thanks!
I think there is a better solution to the problem. Below script was posted back to the editor. As you can see, it needs far less UNIX commands and there is no need to create temporary files.
#! /bin/sh

if [ $# -ne 1 ]; then
        echo "Usage: $0 <name>"
        exit 1
fi

awk -F"," '
BEGIN {
        print "<table>"
        print "<tr><td>Date</td><td>Cost</td><td>Description</td></tr>"
}
$1 == "'$1'" {
        printf("<tr><td>%s</td><td>%s</td><td>%s</td></tr>\n",$4,$3,$2)
}
END {
        print "</table>"
}' expense.txt 

Labels: , ,

Friday, November 03, 2006

Jfind

My colleagues will keep all these find commands in a document. When they need to find certain string in a pile of .java or .jsp documents, they will copy-then-paste from Windows to UNIX terminal.

find . -name "DateUtil" -print;
find . -exec grep "DateUtil" '{}' \; -print;
find . -exec grep "import helper.notification" '{}' \; -print;
find . -exec grep "effectiveDate" '{}' \; -print;
find . -exec grep "ant" '{}' \; -print;

However, they do not know that it can be generalised to one shell function.

jfind()
{
find . \( -name "*.java" -o -name "*.jsp" \) -type f -exec grep -ilF "$*" {} \;
}
jfind will be more efficient than their corresponding find commands because
  • locates only .java and .jsp files (no directory)
  • uses fixed-string search (grep -F == fgrep)
  • uses case-insensitive search
  • suppresses normal output, returns only the file name. The scanning will stop on the first match
So, jfind hooray! jfind hooray!

Labels: