John Hoffmann's Weblog

All | AI | Comedy | Cool Threads | General | Java | Open Source | Robotics | Solaris 10 | Wiki
« Previous month (Jun 2005) | Main | Next month (Aug 2005) »

20050728 Thursday July 28, 2005

Running in Austin Today marks my third morning jog this week. Looks like I managed about 4 miles this morning. I have been a treadmill runner for many years, but having none at my disposal has forced me back to nature. I am really enjoying it so far. I waive to lots of walkers and joggers and send cotten tail bunnies hopping for cover. I'm worried about my leg muscles and joints though. I alreay experience some popping between my right calf and ankle after I've cooled down. I guess I'll have to do more than 15 seconds of stretching at 35 years old. We had several inches of rain last night from significant thunderstorms, so the resididual wetness left a terrific fresh smell in the air and a nice cloud cover to keep the sun at bay. A great start for the day. (2005-07-28 07:09:32.0) Permalink Comments [0]

20050720 Wednesday July 20, 2005

Outsmarting myself Earlier today I was adding 2 additional languages to a localization utility I had written several months ago:
# !/bin/csh
#
## Invoke this script from the english branch in the directory
## of the file(s) that need to be copied to all the locales
##
## use -n switch to echo commands instead of executing them
##
## Example: where pwd is
## /web/www.java.com/en/renderers
##
## /web/tools/cp_l10n.csh -n javacom-rate-this-page.jsp javacom-rb.jsp
##
## output for dry run should be:
## /bin/cp javacom-rate-this-page.jsp /web/www.java.com/de/renderers/javacom-rate-this-page.jsp
## /bin/cp javacom-rb.jsp /web/www.java.com/de/renderers/javacom-rb.jsp
## /bin/cp javacom-rate-this-page.jsp /web/www.java.com/es/renderers/javacom-rate-this-page.jsp
## /bin/cp javacom-rb.jsp /web/www.java.com/es/renderers/javacom-rb.jsp
##
set dry_run=
if ( $#argv > 0 ) then
  if ($argv[1] == "-n") then
    set dry_run=echo
    shift
  endif
  foreach lang (de es fr it ja ko nl pt_BR sv zh_CN zh_TW)
    foreach file (${argv[*]})
      set destination_dir = `pwd | sed 's-/en/-/${lang}/-'`
      eval ${dry_run} /bin/cp ${file} ${destination_dir}/${file}
    end
  end
else
  cat $0 | grep "^##"
endif
While I was in there, the sed command attracted my attention - probably because its the only fun part of part of the script - well the eval of the dry run variable and the grep through $0 for lazy usage message are kinda neat too, but back to the story. I thought, "Gee John, you were really playing fast and loose with your regex. Replacing any occurance of 'en' is crazy. We need '/en/' to be safe to match only the english directory name. So I hastily changed the sed line to:
sed 's-/\/en\//-/\/${lang}\//-g'
Thinking, "Great, now it will only match the exact string '/en/'". Note: '\/en\/' being the escaped form of the pattern - since as everyone knows sed uses '/' as its delimiter...

You all laughing yet?!

Yeah, you seasoned regex guys, and I'm one of you - just having one of those days - you're seeing that when I had originally authored the sed command I chose '-' as the delimiter since '/' was going to be heavily used in the pattern. So now sed was looking for literally this mess: '/\/en\//'. Naturally it found no such patterns in the list of files and the script accomplished nothing.

I've had some half-baked idea that future coding in IDEs might free us from regular expression escaping problems and all syntax for that matter. I envision some visual clue that sets off a regular expression from the surrounding code such that no escaping is needed since the expression is expressed in non-ascii characters. I'll get back to that idea some day, or help me out here - anyone else thought about this?

Not sure if there is any lesson to be learned. The good thing is I used the dry run switch when I invoked the script and therefore had a chance to see that the pattern did not work and the script, if it were not in dry run, would have simply copied the same english file onto itself 11 times. I'm frequently surprised by how often the code I have authored looks foreign to me. Could be related to the fact that I continuously switch between perl, csh, sh, ksh, java, jsp, and jstl. Hard to believe, 50 years into the history of software programming, a single programmer is regularly using 7 or more different syntaxes for "if then else if" branching.

perlif ( ) { } elsif ( ) { }
cshif ( ) then else if ( ) then
shif [ ] then elif [ ] then fi
kshif [ ]; then elif [ ]; then fi
javaif ( ) { } else if ( ) { }
jsp<% if ( ) {%> <%} else if ( ) {%> <%}%>
and my personal favorite, not!
jstl<c:choose><c:when test='${}'></c:when><c:otherwise></c:otherwise></c:choose>

I've annotated another copy of the script, in the event anyone can learn from it:

# !/bin/csh
#
## Invoke this script from the english branch in the directory
## of the file(s) that need to be copied to all the locales
##
## use -n switch to echo commands instead of executing them
##
## Example: where pwd is
## /web/www.java.com/en/renderers
##
## /web/tools/cp_l10n.csh -n javacom-rate-this-page.jsp javacom-rb.jsp
##
## output for dry run should be:
## /bin/cp javacom-rate-this-page.jsp /web/www.java.com/de/renderers/javacom-rate-this-page.jsp
## /bin/cp javacom-rb.jsp /web/www.java.com/de/renderers/javacom-rb.jsp
## /bin/cp javacom-rate-this-page.jsp /web/www.java.com/es/renderers/javacom-rate-this-page.jsp
## /bin/cp javacom-rb.jsp /web/www.java.com/es/renderers/javacom-rb.jsp
##
# be default the dry_run variable is set to nothing
set dry_run=
# check to see if we have more than 0 arguments
if ( $#argv > 0 ) then
  # check to see if the dry run flag is the first argument
  if ($argv[1] == "-n") then
    # if it is set its value to the command "echo"
    set dry_run=echo
    # remove -n from the argument list
    shift
  endif
  # Loop through the set of languages
  foreach lang (de es fr it ja ko nl pt_BR sv zh_CN zh_TW)
    # Inner loop through the remaining arguments which should be file
    # names in the current directory
    foreach file (${argv[*]})
      # create a variable that substitutes the enlgish directory name
      # for the directory name of the language in the outer loop
      # use the back tick to cause the pwd (present working directory)
      # comand to be run and
      # pipe the pwd output into sed which does the language
      # search and replace, the resultant value is stored in
      # the variable destination_dir
      set destination_dir = `pwd | sed 's-/en/-/${lang}/-'`
      # use the eval command to execute the value of the dry_run varaible
      # if dry_run was empty, then /bin/cp gets executed
      # otherwise the echo command gets executed and /bin/cp
      # is simply printed to standard out as text
      eval ${dry_run} /bin/cp ${file} ${destination_dir}/${file}
    end
  end
# if we had less than 1 argument, cat the file and use grep to 
# show only the lines marked as usage instructions designated by ##
# $0 a predefined shell variable set to the path of the script 
else
  cat $0 | grep "^##"
endif

Note, my professor of "Unix Shell Programming" would be very dissappointed that I have repeatedly referred to this utility as a script. He encouraged all his students to call them programs so that Unix administrators who wrote in shell would command the same salaries as programmers. They are slightly different skills, but I'm not sure I place a higher value on one over the other. Shell programming provides more instant gratification in that it usually provides very quick returns on time invested. It also often has higher risk in that you can easily create run away programs that do very bad things if they fail to check for arguments or validate accuracy of constructed paths. Something to watch out for is hooking up a script as a root cronjob. Make sure you test that script in a pure root environment before setting it loose. The ENV for root is often different than what you experience su'd to root. Use the su - , to make sure you're not bringing along any ENV baggage that cronjob root won't have. Whenever possible I also like to adjust the time the cronjob is set to run so that I can watch the results while I am at work, since it is often the case that you set your crons to run at night and its never fun to be greeted first thing the next morning, or the 1st of the month with an unwelcome surprise. (2005-07-20 12:19:18.0) Permalink Comments [3]

20050714 Thursday July 14, 2005

Ergo breaks in Austin On two of my first four days at work in the Austin campus, I have sauntered out to the pond behind building 9. On my return visit this afternoon, I was determined to identify the creatures jumping from the reeds into the pond as I made my way around the perimeter. On my first walk, I saw only fish and dragonflies and heard the kerplop of the skittish mystery creatures. Today, the pond greeted me with a colorfully striped snake about 2 feet long swimming across the surface. Next, I spotted a brown toad swimming away from the shore without a kerplop. Continuing around, I heard several more entries into the pond, but only saw the disturbance in the mossy waters. At the end of circling the pond, there floated upsidedown a mostly eaten 18 inch fish. It had a large mouth and no whiskers, so I'm guessing a bass. Next to the carcass, I spotted a small turtle's head with red stripes. That was more consistent with the amount of rustling and noise I had heard. I am fairly confident it is turtles, not the toads that I am scaring into the water. It is too hot for the toads to stay out of the water and we all know how turtles are sun worshippers. Now a new mystery needs solving, what predator took the life of the fish before the scavengers got to him? We've seen large herons in the area, but I think that fish was too big for them and I beleive they swallow prey whole. If anyone in the Austin area knows the local wildlife, I'd love to hear from ya. I'll bring my Pentax *ist D tomorrow so I can share the experience. (2005-07-14 11:12:15.0) Permalink Comments [2]