friendly ping :)
Omar Polo <[email protected]> wrote:
> Hello everyone,
>
> one year ago there was a thread for grep --null [0] and there seemed to
> be a general agreement (in the diff, not only in how wrong the name
> --null feels.) In the end it wasn't committed, I got distracted and
> continued to happily using my patched ~/bin/grep
>
> [0]: https://marc.info/?l=openbsd-tech&m=160975008513761&w=2
>
> The attached diff was tweaked by benno@ (also after some comments from
> tedu@) and now i've just fixed an issue in printline which reminded me
> that this is still pending.
>
> (we need to print the NUL byte after the filename and skip the next
> separator if we want to follow the GNU grep behavior: freebsd' grep does
> this, netbsd by glancing at the code doesn't.)
>
> One thing that wasn't clear in the other thread is the choice of the
> flag: GNU grep has "-Z, --null" and "-z, --null-data" while our grep has
> -Z to force it to behave as zgrep and no -z. We also can't use -0
> because it stands for "print 0 lines of context" (both in GNU grep and
> ours grep); while it's unlikely that someone is relying on it, it
> currently "works" and dumping NULs into some pipeline not prepared for
> them is not sensible. (e.g. a script that does `| grep -$n'...)
>
> ok?
diff c7b9cff49c7474cbd891cffe3c5679e3c4a02106
95de83f1c7ec1857cafa9126687508fb00d7a2bb
commit - c7b9cff49c7474cbd891cffe3c5679e3c4a02106
commit + 95de83f1c7ec1857cafa9126687508fb00d7a2bb
blob - 5cc228df222c54a0553f289b5da8bbbe6afd171e
blob + e1edae7e432a155ddf71433717f58c8017744386
--- usr.bin/grep/grep.1
+++ usr.bin/grep/grep.1
@@ -49,6 +49,7 @@
.Op Fl -context Ns Op = Ns Ar num
.Op Fl -label Ns = Ns Ar name
.Op Fl -line-buffered
+.Op Fl -null
.Op Ar pattern
.Op Ar
.Ek
@@ -297,6 +298,16 @@ instead of the filename before lines.
Force output to be line buffered.
By default, output is line buffered when standard output is a terminal
and block buffered otherwise.
+.It Fl -null
+Output a zero byte instead of the character that normally follows a
+file name.
+This option makes the output unambiguous, even in the presence of file
+names containing unusual characters like newlines, making the output
+suitable for use with the
+.Fl 0
+option to
+.Xr xargs 1 .
+This option is a non-POSIX extension and may not be portable.
.El
.Sh EXIT STATUS
The
blob - f41b5e20ca68c9e9a36d2f7dd3c44329c621f29b
blob + 279d949fae764262a350e66ce1c21a6864284eb6
--- usr.bin/grep/grep.c
+++ usr.bin/grep/grep.c
@@ -80,6 +80,7 @@ int vflag; /* -v: only show non-matching lines */
int wflag; /* -w: pattern must start and end on word boundaries */
int xflag; /* -x: pattern must match entire line */
int lbflag; /* --line-buffered */
+int nullflag; /* --null */
const char *labelname; /* --label=name */
int binbehave = BIN_FILE_BIN;
@@ -89,6 +90,7 @@ enum {
HELP_OPT,
MMAP_OPT,
LINEBUF_OPT,
+ NULL_OPT,
LABEL_OPT,
};
@@ -134,6 +136,7 @@ static const struct option long_options[] =
{"mmap", no_argument, NULL, MMAP_OPT},
{"label", required_argument, NULL, LABEL_OPT},
{"line-buffered", no_argument, NULL, LINEBUF_OPT},
+ {"null", no_argument, NULL, NULL_OPT},
{"after-context", required_argument, NULL, 'A'},
{"before-context", required_argument, NULL, 'B'},
{"context", optional_argument, NULL, 'C'},
@@ -436,6 +439,9 @@ main(int argc, char *argv[])
case LINEBUF_OPT:
lbflag = 1;
break;
+ case NULL_OPT:
+ nullflag = 1;
+ break;
case HELP_OPT:
default:
usage();
blob - 731bbcc35af4cbf870aaf70ce9913e375142d4d8
blob + 16a1e94a0bcf58498dd4df8d6c7692f1ffdb8045
--- usr.bin/grep/grep.h
+++ usr.bin/grep/grep.h
@@ -68,7 +68,7 @@ extern int cflags, eflags;
extern int Aflag, Bflag, Eflag, Fflag, Hflag, Lflag,
Rflag, Zflag,
bflag, cflag, hflag, iflag, lflag, mflag, nflag, oflag, qflag,
- sflag, vflag, wflag, xflag;
+ sflag, vflag, wflag, xflag, nullflag;
extern int binbehave;
extern const char *labelname;
blob - 33b1094659071e59c719151bc5d0a247ea3cad23
blob + 9aa0a8b5be2fba7f907dd1d065de692a3407e2f7
--- usr.bin/grep/util.c
+++ usr.bin/grep/util.c
@@ -172,13 +172,13 @@ procfile(char *fn)
if (cflag) {
if (!hflag)
- printf("%s:", ln.file);
+ printf("%s%c", ln.file, nullflag ? '\0' : ':');
printf("%llu%s\n", c, overflow ? "+" : "");
}
if (lflag && c != 0)
- printf("%s\n", fn);
+ printf("%s%c", fn, nullflag ? '\0' : '\n');
if (Lflag && c == 0)
- printf("%s\n", fn);
+ printf("%s%c", fn, nullflag ? '\0' : '\n');
if (c && !cflag && !lflag && !Lflag &&
binbehave == BIN_FILE_BIN && nottext && !qflag)
printf("Binary file %s matches\n", fn);
@@ -653,27 +653,32 @@ grep_revstr(unsigned char *str, int len)
void
printline(str_t *line, int sep, regmatch_t *pmatch)
{
- int n;
+ int n, printsep;
n = 0;
+ printsep = !nullflag;
if (!hflag) {
fputs(line->file, stdout);
+ if (nullflag)
+ putchar(0);
++n;
}
if (nflag) {
- if (n)
+ if (n && printsep)
putchar(sep);
printf("%lld", line->line_no);
+ printsep = 1;
++n;
}
if (bflag) {
- if (n)
+ if (n && printsep)
putchar(sep);
printf("%lld", (long long)line->off +
(pmatch ? pmatch->rm_so : 0));
+ printsep = 1;
++n;
}
- if (n)
+ if (n && printsep)
putchar(sep);
if (pmatch)
fwrite(line->dat + pmatch->rm_so,