📄 pcregrep.c
字号:
{ if (name != NULL) fprintf(stdout, "%s:", name); fprintf(stdout, "%d\n", count); }return rc;}/************************************************** Grep a file or recurse into a directory **************************************************/static intgrep_or_recurse(char *filename, BOOL dir_recurse, BOOL show_filenames, BOOL only_one_at_top){int rc = 1;int sep;FILE *in;/* If the file is a directory and we are recursing, scan each file within it.The scanning code is localized so it can be made system-specific. */if ((sep = isdirectory(filename)) != 0 && dir_recurse) { char buffer[1024]; char *nextfile; directory_type *dir = opendirectory(filename); if (dir == NULL) { fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", filename, strerror(errno)); return 2; } while ((nextfile = readdirectory(dir)) != NULL) { int frc; sprintf(buffer, "%.512s%c%.128s", filename, sep, nextfile); frc = grep_or_recurse(buffer, dir_recurse, TRUE, FALSE); if (frc == 0 && rc == 1) rc = 0; } closedirectory(dir); return rc; }/* If the file is not a directory, or we are not recursing, scan it. If this isthe first and only argument at top level, we don't show the file name (unlesswe are only showing the file name). Otherwise, control is via theshow_filenames variable. */in = fopen(filename, "r");if (in == NULL) { fprintf(stderr, "pcregrep: Failed to open %s: %s\n", filename, strerror(errno)); return 2; }rc = pcregrep(in, (filenames_only || (show_filenames && !only_one_at_top))? filename : NULL);fclose(in);return rc;}/************************************************** Usage function **************************************************/static intusage(int rc){fprintf(stderr, "Usage: pcregrep [-Vcfhilnrsvx] [long-options] [pattern] [file1 file2 ...]\n");fprintf(stderr, "Type `pcregrep --help' for more information.\n");return rc;}/************************************************** Help function **************************************************/static voidhelp(void){option_item *op;printf("Usage: pcregrep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");printf("Search for PATTERN in each FILE or standard input.\n");printf("PATTERN must be present if -f is not used.\n");printf("Example: pcregrep -i 'hello.*world' menu.h main.c\n\n");printf("Options:\n");for (op = optionlist; op->one_char != 0; op++) { int n; char s[4]; if (op->one_char > 0) sprintf(s, "-%c,", op->one_char); else strcpy(s, " "); printf(" %s --%s%n", s, op->long_name, &n); n = 30 - n; if (n < 1) n = 1; printf("%.*s%s\n", n, " ", op->help_text); }printf("\n -f<filename> or --file=<filename>\n");printf(" Read patterns from <filename> instead of using a command line option.\n");printf(" Trailing white space is removed; blanks lines are ignored.\n");printf(" There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);printf("\nWith no FILE, read standard input. If fewer than two FILEs given, assume -h.\n");printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");}/************************************************** Handle an option **************************************************/static inthandle_option(int letter, int options){switch(letter) { case -1: help(); exit(0); case 'c': count_only = TRUE; break; case 'h': filenames = FALSE; break; case 'i': options |= PCRE_CASELESS; break; case 'l': filenames_only = TRUE; case 'n': number = TRUE; break; case 'r': recurse = TRUE; break; case 's': silent = TRUE; break; case 'u': options |= PCRE_UTF8; break; case 'v': invert = TRUE; break; case 'x': whole_lines = TRUE; options |= PCRE_ANCHORED; break; case 'V': fprintf(stderr, "pcregrep version %s using ", VERSION); fprintf(stderr, "PCRE version %s\n", pcre_version()); exit(0); break; default: fprintf(stderr, "pcregrep: Unknown option -%c\n", letter); exit(usage(2)); }return options;}/************************************************** Main program **************************************************/intmain(int argc, char **argv){int i, j;int rc = 1;int options = 0;int errptr;const char *error;BOOL only_one_at_top;/* Process the options */for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; /* Missing options */ if (argv[i][1] == 0) exit(usage(2)); /* Long name options */ if (argv[i][1] == '-') { option_item *op; if (strncmp(argv[i]+2, "file=", 5) == 0) { pattern_filename = argv[i] + 7; continue; } for (op = optionlist; op->one_char != 0; op++) { if (strcmp(argv[i]+2, op->long_name) == 0) { options = handle_option(op->one_char, options); break; } } if (op->one_char == 0) { fprintf(stderr, "pcregrep: Unknown option %s\n", argv[i]); exit(usage(2)); } } /* One-char options */ else { char *s = argv[i] + 1; while (*s != 0) { if (*s == 'f') { pattern_filename = s + 1; if (pattern_filename[0] == 0) { if (i >= argc - 1) { fprintf(stderr, "pcregrep: File name missing after -f\n"); exit(usage(2)); } pattern_filename = argv[++i]; } break; } else options = handle_option(*s++, options); } } }pattern_list = (pcre **)malloc(MAX_PATTERN_COUNT * sizeof(pcre *));hints_list = (pcre_extra **)malloc(MAX_PATTERN_COUNT * sizeof(pcre_extra *));if (pattern_list == NULL || hints_list == NULL) { fprintf(stderr, "pcregrep: malloc failed\n"); return 2; }/* Compile the regular expression(s). */if (pattern_filename != NULL) { FILE *f = fopen(pattern_filename, "r"); char buffer[BUFSIZ]; if (f == NULL) { fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pattern_filename, strerror(errno)); return 2; } while (fgets(buffer, sizeof(buffer), f) != NULL) { char *s = buffer + (int)strlen(buffer); if (pattern_count >= MAX_PATTERN_COUNT) { fprintf(stderr, "pcregrep: Too many patterns in file (max %d)\n", MAX_PATTERN_COUNT); return 2; } while (s > buffer && isspace((unsigned char)(s[-1]))) s--; if (s == buffer) continue; *s = 0; pattern_list[pattern_count] = pcre_compile(buffer, options, &error, &errptr, NULL); if (pattern_list[pattern_count++] == NULL) { fprintf(stderr, "pcregrep: Error in regex number %d at offset %d: %s\n", pattern_count, errptr, error); return 2; } } fclose(f); }/* If no file name, a single regex must be given inline */else { if (i >= argc) return usage(2); pattern_list[0] = pcre_compile(argv[i++], options, &error, &errptr, NULL); if (pattern_list[0] == NULL) { fprintf(stderr, "pcregrep: Error in regex at offset %d: %s\n", errptr, error); return 2; } pattern_count++; }/* Study the regular expressions, as we will be running them may times */for (j = 0; j < pattern_count; j++) { hints_list[j] = pcre_study(pattern_list[j], 0, &error); if (error != NULL) { char s[16]; if (pattern_count == 1) s[0] = 0; else sprintf(s, " number %d", j); fprintf(stderr, "pcregrep: Error while studying regex%s: %s\n", s, error); return 2; } }/* If there are no further arguments, do the business on stdin and exit */if (i >= argc) return pcregrep(stdin, NULL);/* Otherwise, work through the remaining arguments as files or directories.Pass in the fact that there is only one argument at top level - this suppressesthe file name if the argument is not a directory. */only_one_at_top = (i == argc - 1);if (filenames_only) filenames = TRUE;for (; i < argc; i++) { int frc = grep_or_recurse(argv[i], recurse, filenames, only_one_at_top); if (frc == 0 && rc == 1) rc = 0; }return rc;}/* End */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -