grep -o ^....

2016-08-24 Thread Ted Unangst
per freebsd bug report:
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=201650

echo "1234 1234 1234" | grep -o ^
1234


Index: util.c
===
RCS file: /cvs/src/usr.bin/grep/util.c,v
retrieving revision 1.55
diff -u -p -r1.55 util.c
--- util.c  4 Apr 2016 05:49:47 -   1.55
+++ util.c  24 Aug 2016 19:11:01 -
@@ -49,7 +49,7 @@
 
 static int linesqueued;
 static int procline(str_t *l, int);
-static int grep_search(fastgrep_t *, char *, size_t, regmatch_t *pmatch);
+static int grep_search(fastgrep_t *, char *, size_t, regmatch_t *pmatch, 
int);
 #ifndef SMALL
 static boolgrep_cmp(const char *, const char *, size_t);
 static voidgrep_revstr(unsigned char *, int);
@@ -192,14 +192,20 @@ procline(str_t *l, int nottext)
offset = 0;
 redo:
if (fg_pattern[i].pattern) {
+   int flags = 0;
+   if (offset)
+   flags |= REG_NOTBOL;
r = grep_search(_pattern[i], l->dat + offset,
-   l->len - offset, );
+   l->len - offset, , flags);
pmatch.rm_so += offset;
pmatch.rm_eo += offset;
} else {
+   int flags = eflags;
+   if (offset)
+   flags |= REG_NOTBOL;
pmatch.rm_so = offset;
pmatch.rm_eo = l->len;
-   r = regexec(_pattern[i], l->dat, 1, , eflags);
+   r = regexec(_pattern[i], l->dat, 1, , flags);
}
if (r == 0 && xflag) {
if (pmatch.rm_so != 0 || pmatch.rm_eo != l->len)
@@ -459,7 +465,8 @@ nonspecial:
  e > s && isword(d[s]) && isword(d[e-1]))
 
 static int
-grep_search(fastgrep_t *fg, char *data, size_t dataLen, regmatch_t *pmatch)
+grep_search(fastgrep_t *fg, char *data, size_t dataLen, regmatch_t *pmatch,
+int flags)
 {
 #ifdef SMALL
return 0;
@@ -476,6 +483,8 @@ grep_search(fastgrep_t *fg, char *data, 
 
/* Only try once at the beginning or ending of the line. */
if (fg->bol || fg->eol) {
+   if (fg->bol && (flags & REG_NOTBOL))
+   return 0;
/* Simple text comparison. */
/* Verify data is >= pattern length before searching on it. */
if (dataLen >= fg->patternLen) {



grep -o

2011-06-20 Thread Ted Unangst
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 -   1.40
+++ grep.1  20 Jun 2011 19:38:55 -
@@ -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 -   1.43
+++ grep.c  20 Jun 2011 19:36:39 -
@@ -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 -   1.16
+++ grep.h  20 Jun 2011 19:34:58 -
@@ -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);
-voidprintline(str_t *line, int sep);
+voidprintline(str_t *line, int sep, regmatch_t *pmatch);
 int fastcomp(fastgrep_t *, const char *);
 voidfgrepcomp(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 -   1.5
+++ queue.c 20 Jun 2011 19:33:23 -
@@ -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 -   1.39
+++ util.c  20 Jun 2011 19:34:30 -
@@ -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 voidgrep_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++) {