📄 grep.c
字号:
/*---------------------------------------------------------------------------
* GREP.C a generalized regular expression parser
*
*
* Copyright (c) 1984 Allen Holub
* Copyright (c) 1984 Software Engineering Consultants
* P.O. Box 5679
* Berkeley, CA. 94705
*
* All rights reserved.
*
* This program may be copied for personal, non-commmercial use
* only, provided that this copyright notice is included in all
* copies and that this program is not modified in any way.
* Copying for any other use without previously obtaining the
* written permission of the author is prohibited.
*
*---------------------------------------------------------------------------
*/
/*
* The algorithm used here is essentially the algorithm in
* Software Tools in Pascal (pp 145f.). Though the routines have
* been changed somewhat to put them into good 'C'.
*
* This program is a healthy subset of the UNIX program of the same
* name. The differences are as follows:
*
* - the -s, -x, and -b options are not supported.
* - the meta-characters ()+? are not supported.
*
* usage is:
* grep [-vclnhyef] [expression] files ...
*
*/
#include <stdio.h>
#include <ctype.h>
#include <malloc.h>
#include <string.h>
#include "tools.h"
#define MAXLINE 256 /* Maximum size of an input line */
#define MAX_EXPR 64 /* Maximum number of regular expressions
* seperated by newlines or | allowed
*/
/* The following global flags are true if a switch was set
* on the command line, false otherwise.
*/
int vflag, yflag, cflag, lflag, nflag, hflag, fflag, iflag;
main(argc, argv)int argc;
char **argv;
{
int i, j, linenum, count;
char line[MAXLINE], displayline[MAXLINE];
int numfiles;
FILE *stream;
int exprc;
TOKEN *exprv[MAX_EXPR];
i = 1;
if (argc < 2)
abort(pr_usage(1));
if (*argv[i] == '-')
/* command line switches ? */
{
expand_sw(argv[i++]);
if (i == argc)
abort(pr_usage(1));
}
/* Pattern string */
if ((exprc = get_expr(exprv, MAX_EXPR, &argv[i++])) == 0)
abort(pr_usage(2));
numfiles = argc - i; /* number of files left to process */
fprintf(stderr, " \n"); /* opening message */
while (i < argc)
{
if (numfiles)
{
stream = fopen(argv[i], "r");
if (stream == NULL)
{
fprintf(stderr, "Can't open %s\n", argv[i++]);
continue;
}
}
else
stream = stdin;
count = 0;
linenum = 1;
while (fgets(line, MAXLINE, stream))
{
strcpy(displayline, line);
if (yflag)
/* MSC routine instead of */
strupr(line);
/* stoupper in tools.c */
for (j = exprc; --j >= 0;)
{
if (matchs(line, exprv[j]))
{
count++;
pr_match(linenum, displayline, argv[i], 1, numfiles);
}
else
pr_match(linenum, displayline, argv[i], 0, numfiles);
linenum++;
}
if (lflag && count)
break;
}
pr_count(numfiles, argv[i], count);
fclose(stream);
i++;
};
abort();
}
/* ----------------------------------------------------------------------- */
pr_count(fcount, fname, count)int fcount, count;
char *fname;
{
if (!cflag)
return 0;
if (fcount > 1)
printf("%-12s: ", fname);
printf("%d\n", count);
}
/* ----------------------------------------------------------------------- */
pr_match(linenum, line, fname, match, numfiles)int linenum, match, numfiles;
char *line, *fname;
{
char buf[80];
if (cflag)
return 0;
if ((vflag && !match) || (!vflag && match))
{
if (!hflag && ((numfiles > 1) || lflag))
printf("%s", fname);
if (lflag)
printf("\n");
else
{
if (nflag)
printf("(%03d)", linenum);
printf(":%s", line);
}
}
}
/* ----------------------------------------------------------------------- */
pr_usage(num)int num;
{
#ifdef DEBUG
fprintf(stderr, "%d ", num);
#endif
fprintf(stderr, "usage: grep [-cefhlnvy] [expression] <files...>\n");
}
/* ----------------------------------------------------------------------- */
abort()
{
exit();
}
/* ----------------------------------------------------------------------- */
expand_sw(str)char *str;
{
vflag = 0;
cflag = 0;
lflag = 0;
nflag = 0;
hflag = 0;
fflag = 0;
yflag = 0;
while (*str)
{
switch (toupper(*str))
{
case '-':
case 'E':
break;
case 'C':
cflag = 1;
break;
case 'F':
fflag = 1;
break;
case 'H':
hflag = 1;
break;
case 'I':
iflag = 1;
break;
case 'L':
lflag = 1;
break;
case 'N':
nflag = 1;
break;
case 'V':
vflag = 1;
break;
case 'Y':
yflag = 1;
break;
default:
pr_usage(3);
abort();
break;
}
str++;
}
}
/* ----------------------------------------------------------------------- */
int do_or(lp, expr, max)char *lp;
TOKEN **expr;
int max;
{
int found;
TOKEN *pat;
char *op;
found = 0;
/*
* Extract regular expressions seperated by OR_SYM's from
* lp and put them into expr. Extract only up to max
* expressions. If yflag is true map string to uppercase first
*/
if (yflag)
strupr(lp);
while (op = in_string(OR_SYM, lp))
{
if (found <= max && (pat = makepat(lp, OR_SYM, iflag)))
{
*expr++ = pat;
found++;
}
lp = ++op;
if (pat == 0)
goto fatal_err;
}
if (found <= max && (pat = makepat(lp, OR_SYM, iflag)))
{
found++;
*expr = pat;
}
if (pat == 0)
{
fatal_err: printf("Illegal expression\n");
exit();
}
return (found);
}
/* ----------------------------------------------------------------------- */
get_expr(expr, max, defexpr)TOKEN *expr[];
int max;
char **defexpr;
{
FILE *stream;
int count;
char line[MAXLINE];
#ifdef DEBUG
int i;
#endif
/* Get regular expressions seperated by | or newlines either
* out of a file or off the command line depending on whether
* the -f flag is set. The expressions are converted into
* pattern templates and pointers to the templates are put into
* the array expr[] (which works similar to argv).
*
* Return the number of expressions found (which can be used in
* a similar fashion to argc).
*/
count = 0;
if (fflag)
{
if ((stream = fopen(*defexpr, "r")) == NULL)
{
fprintf(stderr, "Can't open %s\n", *defexpr);
abort();
}
while ((max - count) && fgets(line, MAXLINE, stream))
count += do_or(line, &expr[count], max - count);
fclose(stream);
}
else
if (count += do_or(*defexpr, &expr[count], max - count))
*defexpr = " ";
#ifdef DEBUG
for (i = count; --i >= 0;)
{
pr_tok(expr[1]);
printf("------------------------------------\n");
}
#endif
return (count);
}
//-------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -