📄 grep.c
字号:
/* * The information in this document is subject to change * without notice and should not be construed as a commitment * by Digital Equipment Corporation or by DECUS. * * Neither Digital Equipment Corporation, DECUS, nor the authors * assume any responsibility for the use or reliability of this * document or the described software. * * Copyright (C) 1980, DECUS * * General permission to copy or modify, but not for profit, is * hereby granted, provided that the above copyright notice is * included and reference made to the fact that reproduction * privileges were granted by DECUS. */#include <stdio.h>#include <stdlib.h>#include <ctype.h>/* * grep * * Runs on the Decus compiler or on vms, On vms, define as: * grep :== "$disk:[account]grep" (native) * grep :== "$disk:[account]grep grep" (Decus) * See below for more information. */char *documentation[] = {"grep searches a file for a given pattern. Execute by"," grep [flags] regular_expression file_list\n","Flags are single characters preceeded by '-':"," -c Only a count of matching lines is printed"," -f Print file name for matching lines switch, see below"," -n Each line is preceeded by its line number"," -v Only print non-matching lines\n","The file_list is a list of files (wildcards are acceptable on RSX modes).","\nThe file name is normally printed if there is a file given.","The -f flag reverses this action (print name no file, not if more).\n",0 };char *patdoc[] = {"The regular_expression defines the pattern to search for. Upper- and","lower-case are always ignored. Blank lines never match. The expression","should be quoted to prevent file-name translation.","x An ordinary character (not mentioned below) matches that character.","'\\' The backslash quotes any character. \"\\$\" matches a dollar-sign.","'^' A circumflex at the beginning of an expression matches the"," beginning of a line.","'$' A dollar-sign at the end of an expression matches the end of a line.","'.' A period matches any character except \"new-line\".","':a' A colon matches a class of characters described by the following","':d' character. \":a\" matches any alphabetic, \":d\" matches digits,","':n' \":n\" matches alphanumerics, \": \" matches spaces, tabs, and","': ' other control characters, such as new-line.","'*' An expression followed by an asterisk matches zero or more"," occurrances of that expression: \"fo*\" matches \"f\", \"fo\""," \"foo\", etc.","'+' An expression followed by a plus sign matches one or more"," occurrances of that expression: \"fo+\" matches \"fo\", etc.","'-' An expression followed by a minus sign optionally matches"," the expression.","'[]' A string enclosed in square brackets matches any character in"," that string, but no others. If the first character in the"," string is a circumflex, the expression matches any character"," except \"new-line\" and the characters in the string. For"," example, \"[xyz]\" matches \"xx\" and \"zyx\", while \"[^xyz]\""," matches \"abc\" but not \"axb\". A range of characters may be"," specified by two characters separated by \"-\". Note that,"," [a-z] matches alphabetics, while [z-a] never matches.","The concatenation of regular expressions is a regular expression.",0};#define LMAX 512#define PMAX 256#define CHAR 1#define BOL 2#define EOL 3#define ANY 4#define CLASS 5#define NCLASS 6#define STAR 7#define PLUS 8#define MINUS 9#define ALPHA 10#define DIGIT 11#define NALPHA 12#define PUNCT 13#define RANGE 14#define ENDPAT 15int cflag=0, fflag=0, nflag=0, vflag=0, nfile=0, debug=0;char *pp, lbuf[LMAX], pbuf[PMAX];extern char *cclass(), *pmatch();/*** Main program - parse arguments & grep *************/main(argc, argv)int argc;char *argv[];{ register char *p; register int c, i; int gotpattern; FILE *f; if (argc <= 1) usage("No arguments"); if (argc == 2 && argv[1][0] == '?' && argv[1][1] == 0) { help(documentation); help(patdoc); return 1; } nfile = argc-1; gotpattern = 0; for (i=1; i < argc; ++i) { p = argv[i]; if (*p == '-') { ++p; while (c = *p++) { switch(tolower(c)) { case '?': help(documentation); break; case 'C': case 'c': ++cflag; break; case 'D': case 'd': ++debug; break; case 'F': case 'f': ++fflag; break; case 'n': case 'N': ++nflag; break; case 'v': case 'V': ++vflag; break; default: usage("Unknown flag"); } } argv[i] = 0; --nfile; } else if (!gotpattern) { compile(p); argv[i] = 0; ++gotpattern; --nfile; } } if (!gotpattern) usage("No pattern"); if (nfile == 0) grep(stdin, 0); else { fflag = fflag ^ (nfile > 0); for (i=1; i < argc; ++i) { if (p = argv[i]) { if ((f=fopen(p, "r")) == NULL) cant(p); else { grep(f, p); fclose(f); } } } } return EXIT_SUCCESS;}/*** Display a file name *******************************/file(s)char *s;{ printf("File %s:\n", s);}/*** Report unopenable file ****************************/cant(s)char *s;{ fprintf(stderr, "%s: cannot open\n", s);}/*** Give good help ************************************/help(hp)char **hp;{ register char **dp; for (dp = hp; *dp; ++dp) printf("%s\n", *dp);}/*** Display usage summary *****************************/usage(s)char *s;{ fprintf(stderr, "?GREP-E-%s\n", s); fprintf(stderr, "Usage: grep [-cfnv] pattern [file ...]. grep ? for help\n"); exit(EXIT_FAILURE);}/*** Compile the pattern into global pbuf[] ************/compile(source)char *source; /* Pattern to compile */{ register char *s; /* Source string pointer */ register char *lp; /* Last pattern pointer */ register int c; /* Current character */ int o; /* Temp */ char *spp; /* Save beginning of pattern */ s = source; if (debug) printf("Pattern = \"%s\"\n", s); pp = pbuf; while (c = *s++) { /* * STAR, PLUS and MINUS are special. */ if (c == '*' || c == '+' || c == '-') { if (pp == pbuf || (o=pp[-1]) == BOL || o == EOL || o == STAR || o == PLUS || o == MINUS) badpat("Illegal occurrance op.", source, s); store(ENDPAT); store(ENDPAT); spp = pp; /* Save pattern end */ while (--pp > lp) /* Move pattern down */ *pp = pp[-1]; /* one byte */ *pp = (c == '*') ? STAR : (c == '-') ? MINUS : PLUS; pp = spp; /* Restore pattern end */ continue; } /* * All the rest. */ lp = pp; /* Remember start */ switch(c) { case '^': store(BOL); break; case '$': store(EOL); break; case '.': store(ANY); break; case '[': s = cclass(source, s); break; case ':': if (*s) { switch(tolower(c = *s++)) { case 'a':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -