Ordinarily, extensions to standard utilities are bad, but I think it's
worth considering when the flag is easily understood and provides a
substantial benefit. I think case insenstive matching in sed qualifies.
The diff below actually implements this behavior two different ways.
Option 1 is to add /i to substitution patterns. Option 2 adds -i to the
command line.
Index: compile.c
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/sed/compile.c,v
retrieving revision 1.31
diff -u -r1.31 compile.c
--- compile.c 27 Oct 2009 23:59:43 -0000 1.31
+++ compile.c 2 Feb 2010 05:11:31 -0000
@@ -57,11 +57,13 @@
int lh_ref;
} *labels[LHSZ];
+static char *get_restring(char *, char **);
static char *compile_addr(char *, struct s_addr *);
static char *compile_ccl(char **, char *);
static char *compile_delimited(char *, char *);
static char *compile_flags(char *, struct s_subst *);
static char *compile_re(char *, regex_t **);
+static void compile_restring(char *, regex_t **, int flags);
static char *compile_subst(char *, struct s_subst *);
static char *compile_text(void);
static char *compile_tr(char *, char **);
@@ -142,6 +144,7 @@
compile_stream(struct s_command **link)
{
char *p;
+ char *restring;
static char *lbuf; /* To avoid excessive malloc calls */
static size_t bufsize;
struct s_command *cmd, *cmd2, *stack;
@@ -305,12 +308,14 @@
err(COMPILE, "substitute pattern can not be"
" delimited by newline or backslash");
cmd->u.s = xmalloc(sizeof(struct s_subst));
- p = compile_re(p, &cmd->u.s->re);
+ p = get_restring(p, &restring);
if (p == NULL)
err(COMPILE, "unterminated substitute pattern");
--p;
p = compile_subst(p, cmd->u.s);
p = compile_flags(p, cmd->u.s);
+ compile_restring(restring, &cmd->u.s->re,
cmd->u.s->ignorecase ?
+ REG_ICASE : 0);
EATSPACE();
if (*p == ';') {
p++;
@@ -418,27 +423,45 @@
* Returns a pointer to the first character after the final delimiter
* or NULL in the case of a non terminated regular expression. The regexp
* pointer is set to the compiled regular expression.
- * Cflags are passed to regcomp.
*/
-static char *
-compile_re(char *p, regex_t **repp)
+static void
+compile_restring(char *re, regex_t **repp, int flags)
{
int eval;
+
+ *repp = xmalloc(sizeof(regex_t));
+ if ((eval = regcomp(*repp, re, flags | (Eflag ? REG_EXTENDED : 0) |
+ (iflag ? REG_ICASE : 0))) != 0)
+ err(COMPILE, "RE error: %s", strregerror(eval, *repp));
+ if (maxnsub < (*repp)->re_nsub)
+ maxnsub = (*repp)->re_nsub;
+ free(re);
+}
+
+static char *
+get_restring(char *p, char **rep)
+{
char *re;
re = xmalloc(strlen(p) + 1); /* strlen(re) <= strlen(p) */
p = compile_delimited(p, re);
if (p && strlen(re) == 0) {
- *repp = NULL;
+ *rep = NULL;
free(re);
return (p);
}
- *repp = xmalloc(sizeof(regex_t));
- if (p && (eval = regcomp(*repp, re, Eflag ? REG_EXTENDED : 0)) != 0)
- err(COMPILE, "RE error: %s", strregerror(eval, *repp));
- if (maxnsub < (*repp)->re_nsub)
- maxnsub = (*repp)->re_nsub;
- free(re);
+ *rep = re;
+ return (p);
+}
+
+
+static char *
+compile_re(char *p, regex_t **repp)
+{
+ char *re;
+
+ p = get_restring(p, &re);
+ compile_restring(re, repp, 0);
return (p);
}
@@ -549,6 +572,9 @@
" substitute flags");
gn = 1;
s->n = 0;
+ break;
+ case 'i':
+ s->ignorecase = 1;
break;
case '\0':
case '\n':
Index: defs.h
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/sed/defs.h,v
retrieving revision 1.4
diff -u -r1.4 defs.h
--- defs.h 16 Oct 2008 16:34:32 -0000 1.4
+++ defs.h 2 Feb 2010 04:50:22 -0000
@@ -60,6 +60,7 @@
struct s_subst {
int n; /* Occurrence to subst. */
int p; /* True if p flag */
+ int ignorecase;
char *wfile; /* NULL if no wfile */
int wfd; /* Cached file descriptor */
regex_t *re; /* Regular expression */
Index: extern.h
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/sed/extern.h,v
retrieving revision 1.6
diff -u -r1.6 extern.h
--- extern.h 7 Aug 2009 03:30:56 -0000 1.6
+++ extern.h 2 Feb 2010 05:10:35 -0000
@@ -41,7 +41,7 @@
extern u_long linenum;
extern int appendnum;
extern int lastline;
-extern int Eflag, aflag, eflag, nflag;
+extern int Eflag, aflag, eflag, iflag, nflag;
extern char *fname;
void cfclose(struct s_command *, struct s_command *);
Index: main.c
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/sed/main.c,v
retrieving revision 1.17
diff -u -r1.17 main.c
--- main.c 27 Oct 2009 23:59:43 -0000 1.17
+++ main.c 2 Feb 2010 05:18:03 -0000
@@ -78,7 +78,7 @@
*/
static struct s_flist *files, **fl_nextp = &files;
-int Eflag, aflag, eflag, nflag;
+int Eflag, aflag, eflag, iflag, nflag;
/*
* Current file and line number; line numbers restart across compilation
@@ -97,7 +97,7 @@
int c, fflag;
fflag = 0;
- while ((c = getopt(argc, argv, "Eae:f:nru")) != -1)
+ while ((c = getopt(argc, argv, "Eae:f:inru")) != -1)
switch (c) {
case 'E':
case 'r':
@@ -114,6 +114,9 @@
fflag = 1;
add_compunit(CU_FILE, optarg);
break;
+ case 'i':
+ iflag = 1;
+ break;
case 'n':
nflag = 1;
break;
@@ -123,8 +126,8 @@
default:
case '?':
(void)fprintf(stderr,
- "usage: sed [-aEnru] command [file ...]\n"
- " sed [-aEnru] [-e command] [-f command_file]
[file ...]\n");
+ "usage: sed [-aEinru] command [file ...]\n"
+ " sed [-aEinru] [-e command] [-f
command_file] [file ...]\n");
exit(1);
}
argc -= optind;
Index: sed.1
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/sed/sed.1,v
retrieving revision 1.35
diff -u -r1.35 sed.1
--- sed.1 10 Jan 2010 10:53:33 -0000 1.35
+++ sed.1 2 Feb 2010 05:17:35 -0000
@@ -40,7 +40,7 @@
.Nd stream editor
.Sh SYNOPSIS
.Nm sed
-.Op Fl aEnru
+.Op Fl aEinru
.Ar command
.Op Ar
.Nm sed
@@ -94,6 +94,8 @@
.Ar command_file
to the list of commands.
The editing commands should each be listed on a separate line.
+.It Fl i
+Perform case insensitive matching.
.It Fl r
An alias for
.Fl E ,
@@ -435,6 +437,8 @@
.It g
Make the substitution for all non-overlapping matches of the
regular expression, not just the first one.
+.It i
+Perform case insensitive matching.
.It p
Write the pattern space to standard output if a replacement was made.
If the replacement string is identical to that which it replaces, it
@@ -529,7 +533,7 @@
specification.
.Pp
The flags
-.Op Fl aEru
+.Op Fl aEiru
are extensions to that specification.
.Pp
The use of newlines to separate multiple commands on the command line