📄 pcregrep.c
字号:
endptr = buffer + bufflength; /* Adjust any last match point */ if (lastmatchnumber > 0) lastmatchrestart -= MBUFTHIRD; } } /* Loop through the whole file *//* End of file; print final "after" lines if wanted; do_after_lines setshyphenpending if it prints something. */if (!only_matching && !count_only) { do_after_lines(lastmatchnumber, lastmatchrestart, endptr, printname); hyphenpending |= endhyphenpending; }/* Print the file name if we are looking for those without matches and therewere none. If we found a match, we won't have got this far. */if (filenames == FN_NOMATCH_ONLY) { fprintf(stdout, "%s\n", printname); return 0; }/* Print the match count if wanted */if (count_only) { if (printname != NULL) fprintf(stdout, "%s:", printname); fprintf(stdout, "%d\n", count); }return rc;}/************************************************** Grep a file or recurse into a directory **************************************************//* Given a path name, if it's a directory, scan all the files if we arerecursing; if it's a file, grep it.Arguments: pathname the path to investigate dir_recurse TRUE if recursing is wanted (-r or -drecurse) only_one_at_top TRUE if the path is the only one at toplevelReturns: 0 if there was at least one match 1 if there were no matches 2 there was some kind of errorHowever, file opening failures are suppressed if "silent" is set.*/static intgrep_or_recurse(char *pathname, BOOL dir_recurse, BOOL only_one_at_top){int rc = 1;int sep;FILE *in;/* If the file name is "-" we scan stdin */if (strcmp(pathname, "-") == 0) { return pcregrep(stdin, (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))? stdin_name : NULL); }/* If the file is a directory, skip if skipping or if we are recursing, scaneach file within it, subject to any include or exclude patterns that were set.The scanning code is localized so it can be made system-specific. */if ((sep = isdirectory(pathname)) != 0) { if (dee_action == dee_SKIP) return 1; if (dee_action == dee_RECURSE) { char buffer[1024]; char *nextfile; directory_type *dir = opendirectory(pathname); if (dir == NULL) { if (!silent) fprintf(stderr, "pcregrep: Failed to open directory %s: %s\n", pathname, strerror(errno)); return 2; } while ((nextfile = readdirectory(dir)) != NULL) { int frc, blen; sprintf(buffer, "%.512s%c%.128s", pathname, sep, nextfile); blen = strlen(buffer); if (exclude_compiled != NULL && pcre_exec(exclude_compiled, NULL, buffer, blen, 0, 0, NULL, 0) >= 0) continue; if (include_compiled != NULL && pcre_exec(include_compiled, NULL, buffer, blen, 0, 0, NULL, 0) < 0) continue; frc = grep_or_recurse(buffer, dir_recurse, FALSE); if (frc > 1) rc = frc; else if (frc == 0 && rc == 1) rc = 0; } closedirectory(dir); return rc; } }/* If the file is not a directory and not a regular file, skip it if that'sbeen requested. */else if (!isregfile(pathname) && DEE_action == DEE_SKIP) return 1;/* Control reaches here if we have a regular file, or if we have a directoryand recursion or skipping was not requested, or if we have anything else andskipping was not requested. The scan proceeds. If this is the first and onlyargument at top level, we don't show the file name, unless we are only showingthe file name, or the filename was forced (-H). */in = fopen(pathname, "r");if (in == NULL) { if (!silent) fprintf(stderr, "pcregrep: Failed to open %s: %s\n", pathname, strerror(errno)); return 2; }rc = pcregrep(in, (filenames > FN_DEFAULT || (filenames == FN_DEFAULT && !only_one_at_top))? pathname : NULL);fclose(in);return rc;}/************************************************** Usage function **************************************************/static intusage(int rc){option_item *op;fprintf(stderr, "Usage: pcregrep [-");for (op = optionlist; op->one_char != 0; op++) { if (op->one_char > 0) fprintf(stderr, "%c", op->one_char); }fprintf(stderr, "] [long options] [pattern] [files]\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 neither -e nor -f is used.\n");printf("\"-\" can be used as a file name to mean STDIN.\n\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("\nWhen reading patterns from a file instead of using a command line option,\n");printf("trailing white space is removed and blank lines are ignored.\n");printf("There is a maximum of %d patterns.\n", MAX_PATTERN_COUNT);printf("\nWith no FILEs, 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 a single-letter, no data option **************************************************/static inthandle_option(int letter, int options){switch(letter) { case N_HELP: help(); exit(0); case 'c': count_only = TRUE; break; case 'F': process_options |= PO_FIXED_STRINGS; break; case 'H': filenames = FN_FORCE; break; case 'h': filenames = FN_NONE; break; case 'i': options |= PCRE_CASELESS; break; case 'l': filenames = FN_ONLY; break; case 'L': filenames = FN_NOMATCH_ONLY; break; case 'M': multiline = TRUE; options |= PCRE_MULTILINE|PCRE_FIRSTLINE; break; case 'n': number = TRUE; break; case 'o': only_matching = TRUE; break; case 'q': quiet = TRUE; break; case 'r': dee_action = dee_RECURSE; break; case 's': silent = TRUE; break; case 'u': options |= PCRE_UTF8; break; case 'v': invert = TRUE; break; case 'w': process_options |= PO_WORD_MATCH; break; case 'x': process_options |= PO_LINE_MATCH; 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;}/************************************************** Construct printed ordinal **************************************************//* This turns a number into "1st", "3rd", etc. */static char *ordin(int n){static char buffer[8];char *p = buffer;sprintf(p, "%d", n);while (*p != 0) p++;switch (n%10) { case 1: strcpy(p, "st"); break; case 2: strcpy(p, "nd"); break; case 3: strcpy(p, "rd"); break; default: strcpy(p, "th"); break; }return buffer;}/************************************************** Compile a single pattern **************************************************//* When the -F option has been used, this is called for each substring.Otherwise it's called for each supplied pattern.Arguments: pattern the pattern string options the PCRE options filename the file name, or NULL for a command-line pattern count 0 if this is the only command line pattern, or number of the command line pattern, or linenumber for a pattern from a fileReturns: TRUE on success, FALSE after an error*/static BOOLcompile_single_pattern(char *pattern, int options, char *filename, int count){char buffer[MBUFTHIRD + 16];const char *error;int errptr;if (pattern_count >= MAX_PATTERN_COUNT) { fprintf(stderr, "pcregrep: Too many %spatterns (max %d)\n", (filename == NULL)? "command-line " : "", MAX_PATTERN_COUNT); return FALSE; }sprintf(buffer, "%s%.*s%s", prefix[process_options], MBUFTHIRD, pattern, suffix[process_options]);pattern_list[pattern_count] = pcre_compile(buffer, options, &error, &errptr, pcretables);if (pattern_list[pattern_count++] != NULL) return TRUE;/* Handle compile errors */errptr -= (int)strlen(prefix[process_options]);if (errptr > (int)strlen(pattern)) errptr = (int)strlen(pattern);if (filename == NULL) { if (count == 0) fprintf(stderr, "pcregrep: Error in command-line regex " "at offset %d: %s\n", errptr, error); else fprintf(stderr, "pcregrep: Error in %s command-line regex " "at offset %d: %s\n", ordin(count), errptr, error); }else { fprintf(stderr, "pcregrep: Error in regex in line %d of %s " "at offset %d: %s\n", count, filename, errptr, error); }return FALSE;}/************************************************** Compile one supplied pattern **************************************************//* When the -F option has been used, each string may be a list of strings,separated by newlines. They will be matched literally.Arguments: pattern the pattern string options the PCRE options filename the file name, or NULL for a command-line pattern count 0 if this is the only command line pattern, or number of the command line pattern, or linenumber for a pattern from a fileReturns: TRUE on success, FALSE after an error*/static BOOLcompile_pattern(char *pattern, int options, char *filename, int count){if ((process_options & PO_FIXED_STRINGS) != 0) { char buffer[MBUFTHIRD]; for(;;) { char *p = strchr(pattern, '\n'); if (p == NULL) return compile_single_pattern(pattern, options, filename, count); sprintf(buffer, "%.*s", p - pattern, pattern); pattern = p + 1; if (!compile_single_pattern(buffer, options, filename, count)) return FALSE; } }else return compile_single_pattern(pattern, options, filename, count);}/************************************************** Main program **************************************************//* Returns 0 if something matched, 1 if nothing matched, 2 after an error. */intmain(int argc, char **argv){int i, j;int rc = 1;int pcre_options = 0;int cmd_pattern_count = 0;int errptr;BOOL only_one_at_top;char *patterns[MAX_PATTERN_COUNT];const char *locale_from = "--locale";const char *error;/* Process the options */for (i = 1; i < argc; i++) { option_item *op = NULL; char *option_data = (char *)""; /* default to keep compiler happy */ BOOL longop; BOOL longopwasequals = FALSE; if (argv[i][0] != '-') break; /* If we hit an argument that is just "-", it may be a reference to STDIN, but only if we have previously had -e or -f to define the patterns. */ if (argv[i][1] == 0) { if (pattern_filename != NULL || pattern_count > 0) break; else exit(usage(2)); } /* Handle a long name option, or -- to terminate the options */ if (argv[i][1] == '-') { char *arg = argv[i] + 2; char *argequals = strchr(arg, '='); if (*arg == 0) /* -- terminates options */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -