this was proposed a while ago, but got sidetracked by some nonstandard 
option discussion. bringing it back in slightly different form.

-o only prints the matching parts of a line, not the entire line.  While 
this is possible using awk, the same could be said of everything grep 
does.  It is intended to match the behavior of the same option in gnu 
grep.

Index: grep.1
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/grep/grep.1,v
retrieving revision 1.40
diff -u -r1.40 grep.1
--- grep.1      4 Mar 2011 03:11:22 -0000       1.40
+++ grep.1      20 Jun 2011 19:38:55 -0000
@@ -38,7 +38,7 @@
 .Sh SYNOPSIS
 .Nm grep
 .Bk -words
-.Op Fl abcEFGHhIiLlnqRsUVvwxZ
+.Op Fl abcEFGHhIiLlnoqRsUVvwxZ
 .Op Fl A Ar num
 .Op Fl B Ar num
 .Op Fl C Ns Op Ar num
@@ -228,6 +228,8 @@
 .Fl q
 is
 specified.
+.It Fl o
+Print each match, but only the match, not the containing line.
 .It Fl q
 Quiet mode:
 suppress normal output.
Index: grep.c
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/grep/grep.c,v
retrieving revision 1.43
diff -u -r1.43 grep.c
--- grep.c      4 Mar 2011 03:11:23 -0000       1.43
+++ grep.c      20 Jun 2011 19:36:39 -0000
@@ -74,6 +74,7 @@
 int     iflag;         /* -i: ignore case */
 int     lflag;         /* -l: only show names of files with matches */
 int     nflag;         /* -n: show line numbers in front of matching lines */
+int     oflag;         /* -o: print each match */
 int     qflag;         /* -q: quiet mode (don't output anything) */
 int     sflag;         /* -s: silent mode (ignore errors) */
 int     vflag;         /* -v: only show non-matching lines */
@@ -117,9 +118,9 @@
 }
 
 #ifdef NOZ
-static char *optstr = "0123456789A:B:CEFGHILRUVabce:f:hilnqrsuvwxy";
+static char *optstr = "0123456789A:B:CEFGHILRUVabce:f:hilnoqrsuvwxy";
 #else
-static char *optstr = "0123456789A:B:CEFGHILRUVZabce:f:hilnqrsuvwxy";
+static char *optstr = "0123456789A:B:CEFGHILRUVZabce:f:hilnoqrsuvwxy";
 #endif
 
 struct option long_options[] =
@@ -382,6 +383,9 @@
                        break;
                case 'n':
                        nflag = 1;
+                       break;
+               case 'o':
+                       oflag = 1;
                        break;
                case 'q':
                        qflag = 1;
Index: grep.h
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/grep/grep.h,v
retrieving revision 1.16
diff -u -r1.16 grep.h
--- grep.h      4 Mar 2011 03:11:23 -0000       1.16
+++ grep.h      20 Jun 2011 19:34:58 -0000
@@ -65,7 +65,7 @@
 /* Command line flags */
 extern int      Aflag, Bflag, Eflag, Fflag, Gflag, Hflag, Lflag,
                 Rflag, Zflag,
-                bflag, cflag, hflag, iflag, lflag, nflag, qflag, sflag,
+                bflag, cflag, hflag, iflag, lflag, nflag, oflag, qflag, sflag,
                 vflag, wflag, xflag;
 extern int      binbehave;
 
@@ -84,7 +84,7 @@
 void           *grep_malloc(size_t size);
 void           *grep_calloc(size_t nmemb, size_t size);
 void           *grep_realloc(void *ptr, size_t size);
-void            printline(str_t *line, int sep);
+void            printline(str_t *line, int sep, regmatch_t *pmatch);
 int             fastcomp(fastgrep_t *, const char *);
 void            fgrepcomp(fastgrep_t *, const char *);
 
Index: queue.c
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/grep/queue.c,v
retrieving revision 1.5
diff -u -r1.5 queue.c
--- queue.c     9 Feb 2006 09:54:47 -0000       1.5
+++ queue.c     20 Jun 2011 19:33:23 -0000
@@ -107,7 +107,7 @@
        queue_t *item;
 
        while ((item = dequeue()) != NULL) {
-               printline(&item->data, '-');
+               printline(&item->data, '-', NULL);
                free_item(item);
        }
 }
Index: util.c
===================================================================
RCS file: /home/tedu/cvs/src/usr.bin/grep/util.c,v
retrieving revision 1.39
diff -u -r1.39 util.c
--- util.c      2 Jul 2010 22:18:03 -0000       1.39
+++ util.c      20 Jun 2011 19:34:30 -0000
@@ -48,9 +48,9 @@
 
 static int     linesqueued;
 static int     procline(str_t *l, int);
-static int     grep_search(fastgrep_t *, unsigned char *, size_t, regmatch_t 
*pmatch);
+static int     grep_search(fastgrep_t *, char *, size_t, regmatch_t *pmatch);
 #ifndef SMALL
-static int     grep_cmp(const unsigned char *, const unsigned char *, size_t);
+static int     grep_cmp(const char *, const char *, size_t);
 static void    grep_revstr(unsigned char *, int);
 #endif
 
@@ -169,19 +169,25 @@
 {
        regmatch_t      pmatch;
        int             c, i, r;
+       int             offset;
 
+       c = 0;
+       i = 0;
        if (matchall) {
-               c = !vflag;
                goto print;
        }
 
-       for (c = i = 0; i < patterns; i++) {
+       for (i = 0; i < patterns; i++) {
+               offset = 0;
+redo:
                if (fg_pattern[i].pattern) {
-                       r = grep_search(&fg_pattern[i], (unsigned char *)l->dat,
-                           l->len, &pmatch);
+                       r = grep_search(&fg_pattern[i], l->dat + offset,
+                           l->len - offset, &pmatch);
+                       pmatch.rm_so += offset;
+                       pmatch.rm_eo += offset;
                } else {
-                       pmatch.rm_so = 0;
-                       pmatch.rm_eo = l->len;
+                       pmatch.rm_so = offset;
+                       pmatch.rm_eo = l->len - offset;
                        r = regexec(&r_pattern[i], l->dat, 1, &pmatch, eflags);
                }
                if (r == 0 && xflag) {
@@ -189,14 +195,18 @@
                                r = REG_NOMATCH;
                }
                if (r == 0) {
-                       c++;
+                       c = 1;
+                       if (oflag)
+                               goto print;
                        break;
                }
        }
+       if (oflag)
+               return c;
+print:
        if (vflag)
                c = !c;
 
-print:
        if (c && binbehave == BIN_FILE_BIN && nottext)
                return c; /* Binary file */
 
@@ -210,12 +220,17 @@
                        if (Bflag > 0)
                                printqueue();
                        linesqueued = 0;
-                       printline(l, ':');
+                       printline(l, ':', oflag ? &pmatch : NULL);
                } else {
-                       printline(l, '-');
+                       printline(l, '-', oflag ? &pmatch : NULL);
                        tail--;
                }
        }
+       if (oflag && !matchall) {
+
+               offset = pmatch.rm_eo;
+               goto redo;
+       }
        return c;
 }
 
@@ -424,7 +439,7 @@
          e > s && isword(d[s]) && isword(d[e-1]))
 
 static int
-grep_search(fastgrep_t *fg, unsigned char *data, size_t dataLen, regmatch_t 
*pmatch)
+grep_search(fastgrep_t *fg, char *data, size_t dataLen, regmatch_t *pmatch)
 {
 #ifdef SMALL
        return 0;
@@ -476,7 +491,7 @@
                        /* Shift if within bounds, otherwise, we are done. */
                        if (j == fg->patternLen)
                                break;
-                       j -= fg->qsBc[data[j - fg->patternLen - 1]];
+                       j -= fg->qsBc[(unsigned char)data[j - fg->patternLen - 
1]];
                } while (j >= fg->patternLen);
        } else {
                /* Quick Search algorithm. */
@@ -497,7 +512,7 @@
                        if (j + fg->patternLen == dataLen)
                                break;
                        else
-                               j += fg->qsBc[data[j + fg->patternLen]];
+                               j += fg->qsBc[(unsigned char)data[j + 
fg->patternLen]];
                } while (j <= (dataLen - fg->patternLen));
        }
 
@@ -540,7 +555,7 @@
  *             -1 on success
  */
 static int
-grep_cmp(const unsigned char *pattern, const unsigned char *data, size_t len)
+grep_cmp(const char *pattern, const char *data, size_t len)
 {
        int i;
 
@@ -569,7 +584,7 @@
 #endif
 
 void
-printline(str_t *line, int sep)
+printline(str_t *line, int sep, regmatch_t *pmatch)
 {
        int n;
 
@@ -592,6 +607,10 @@
        }
        if (n)
                putchar(sep);
-       fwrite(line->dat, line->len, 1, stdout);
+       if (pmatch)
+               fwrite(line->dat + pmatch->rm_so,
+                   pmatch->rm_eo - pmatch->rm_so, 1, stdout);
+       else
+               fwrite(line->dat, line->len, 1, stdout);
        putchar('\n');
 }

Reply via email to