From: Wayne E Baisley (email@example.com)
Date: Sat Oct 14 2000 - 21:26:48 PDT
Maggie, you're beautiful! Of course, if I were doing it, for heavy-
handed, yet subtle, comic effect, I would have "embellished" Gore's by
adding a letter or two to make whoppergrams. Which is why I'm not a
cartoonist. Or stand-up comedian. Or the list-monitors' pet.
To get with the techno-nerd program, I thought I'd share a little bit
of perl I wrote to modify user login scripts, a year or so ago. This
probably belongs on a perl list, so I thought it best to FoRK it. ;-}
The situation was that we had 20-30 thousand files with code like this
if [ -e /usr/local/etc/fermi.upsII.shrc ]
if [ -r /usr/local/etc/fermi.upsII.shrc ]
if [ -e /usr/local/etc/fermi.shrc ]
if [ -r /usr/local/etc/fermi.shrc ]
[yeah, it's ugly. I didn't write it!]
that we wanted to replace with new stuff. With many variations in
spacing, intervening comments, echo commands, and so on, not to mention
both shell families. So, I picked an approach that took 50 different
known code fragments and turned them into regular expressions.
Whenever an expression matched, that chunk of code got commented out
(using ': #' which works universally), and the new boilerplate setup
code got prefixed to the file. Worked marvelously, to my great relief.
Here's the code that generates the regular expressions:
# patternize does the heavy lifting in doctoring the
# pattern-matching strings.
# This routine does two different things to the input string:
# 1) It quotes all of the metacharacters (and trims the string).
# 2) It generalizes certain known character sequences.
# In several places, we generalize things like parentheses and brackets,
# single and double quotes, in such a way that they won't necessarily
# or match. This is perfectly fine, because the shell will have been
# those rules. We can afford to match impossible supersets. In the
# case, we'll end up overriding a chunk of code that wasn't working.
# The generalizations are quite involved in places, and can be
# fragile, since they can easily interfere with each other.
# Grab the input pattern string.
$_ = $_;
# Trim all leading and trailing newlines.
# Quote all of the regular expression metacharacters.
# Allow for an optional trailing semicolon. Another pattern mangling
# step below will allow for embedded semicolons, but that won't cover
# single-line patterns.
# Allow for intervening echo commands. This consist of the command
# itself, plus a string we'll call ECHOJUNK for now, possibly surrounded
# by single or double quote marks (we're not overly picky about their
# matching or being balanced), possibly followed by a semicolon.
# Turn new-lines into a pattern to match arbitrary whitespace.
# Turn arbitrary whitespace into a pattern to match mandatory
# Collapse the results of the previous steps into appropriate patterns.
# Finish our handling of intervening echo commands. Move the optional
# whitespace inside the parentheses for the whole optional echo string.
# Expand the ECHOJUNK placeholder to match anything but control
# which terminate lines, various quote marks, and the semicolon.
# Generalize the file test options to match all of the usual cases:
# if -a, if -e, if -f, if -r, if -s, and if -x.
# Make sure comment lines in patterns don't bleed to the following
# Generalize the sourcing of certain files (/usr/local/etc/fermi.*,
# /usr/local/etc/setpath.*, /usr/local/etc/setups.*, and
# to allow either the . or source command. Besides reducing the number
# patterns needed, this also catches bash variants.
# Generalize the sourcing of the users' .shrc files, similar to the
# Make the spacing optional in "if (", "( -", and " )" strings, and
# to match either parentheses or brackets (we don't care if they don't
# Generalize certain strings to match bash, ksh or sh.
# Generalize anded tests to match "-a" or "] && ["
# Allow intervening comments, but disallow a trailing comment.
# Generalize to match fermi(.upsII) and setups(II). Also match either
# extension in the setups(II).(c)sh and setpath.(c)sh files.
# Match either fi or endif to end an if block
# Generalize /usr/local/etc to match /usr/local/etc, /fnal/ups/etc, and
# Allow for ~/.shrc and ~username/.shrc forms.
# Let semicolons be followed by optional blanks and tabs
# Put the leading newline back on the pattern, with optional blanks and
# Match any trailing blanks and tabs.
# All done.
See the whole thing at:
And some explanation at:
This archive was generated by hypermail 2b29 : Sat Oct 14 2000 - 21:32:14 PDT