Regular Expression delimiters

Dan Bernstein bernsten at phoenix.Princeton.EDU
Thu Apr 13 07:19:58 AEST 1989


So far, nobody has given an answer to this question that handles more
than a few special cases. Now Chris Torek gives up completely.

Here are some solutions, all thoroughly tested, from the devious mind
that brought you the aliases `quote' and `makealias'. Each example
munges $ans into $pattern, so that sed "s/$pattern/whatever/g" acts
as if it had a literal $ans in the first position.

sh, if you have printenv:
  export ans ; pattern="`printenv ans | sed 's-\([\.\*\[\\\^\$\/]\)-\\\\\1-g'`"

sh, if you have a working echo (whose only caveat is -n):
  pattern="`(echo -n \"$ans\";echo '') | sed 's-\([\.\*\[\\\^\$\/]\)-\\\\\1-g'`"
  NOTE: Chris, want to take back that ``no workaround''?

csh, if you have a working /bin/echo (whose only caveat is -n):
  set pattern="`(echo -n "\"\$ans\"";echo '')
	          | sed 's-\([\.\*\[\\\^\"\$"\/]\)-\\\1-g'`"

csh, if you have a working builtin echo (whose only caveat is -n):
  set pattern="`echo "\"\$ans\"" | sed 's-\([\.\*\[\\\^\"\$"\/]\)-\\\1-g'`"
  NOTE: csh parses builtins strangely, so this works even if ans is "-n ...".

sh, on any machine (put it all on one line):
  pattern="`sed \"$ans\" 2>&1 | sed 's/^Unrecognized command: //'
             | sed 's-\([\.\*\[\\\^\$\/]\)-\\\\\1-g'`"
  CAVEAT: Does not work if $ans contains newlines.

csh, on any machine (put it all on one line):
  set pattern="`sed "\"\$ans\"" |& sed 's/^Unrecognized command: //'
	     | sed 's-\([\.\*\[\\\^\$\/]\)-\\\1-g'`"
  ANTI-CAVEAT: Because csh is csh, this one works if $ans contains newlines.

Some notes about the last two: The sequence ^A (appearing twice in
each---but not the ^U) can be any (identical) string upon which sed
will choke; I use the control character. The general idea of

  sed "^A$ans" 2>&1 | sed 's/^Unrecognized command: ^A//'

is to somehow manage to get that environment variable into the
input-output stream, which is difficult if both echo and printenv
are screwed. Other similar replacements include using ls imaginatively
and then stripping off the `file not found', etc.

It wouldn't take much work to make a `literal' alias, by feeding the
above ideas through `makealias', so that all you'd have to do for this
problem is type

  sed "s/`literal ans`/whatever/g"

Those who have seen my csh aliases `quote' and `makealias' know both
that I have a masochistic enjoyment of these problems and that my
solutions work. So unless I've screwed up, let's cut the discussion.

---Dan Bernstein, bernsten at phoenix.princeton.edu



More information about the Comp.unix.questions mailing list