1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <regex.h>
static void do_grep(FILE *const in, const char *const filename, regex_t *const pattern, const int use_ansi)
{
char *line = NULL;
size_t size = 0;
ssize_t len;
unsigned long linenum = 0UL;
regmatch_t match[2];
while (1) {
len = getline(&line, &size, in);
if (len < (ssize_t)0)
return;
if (len > (ssize_t)0 && line[len - 1] == '\n')
line[--len] = '\0';
linenum++;
if (regexec(pattern, line, 1, match, 0) == REG_NOMATCH)
continue;
printf("%s: %lu: ", filename, linenum);
if (use_ansi) {
if (match[0].rm_so > 0)
fwrite(line, match[0].rm_so, 1, stdout);
if (match[0].rm_eo > match[0].rm_so) {
printf("\033[1;31m");
fwrite(line + match[0].rm_so, match[0].rm_eo - match[0].rm_so, 1, stdout);
}
printf("\033[0m");
if (match[0].rm_eo < len)
fwrite(line + match[0].rm_eo, len - match[0].rm_eo, 1, stdout);
} else
fwrite(line, len, 1, stdout);
putc('\n', stdout);
}
}
int main(int argc, char *argv[])
{
regex_t pattern;
int result, arg;
FILE *in;
int use_ansi;
use_ansi = isatty(STDOUT_FILENO);
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s PATTERN [ FILES ... ]\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
result = regcomp(&pattern, argv[1], REG_NEWLINE);
if (result) {
const size_t length = regerror(result, &pattern, NULL, 0);
char *errmsg;
errmsg = malloc(length + 1);
if (!errmsg) {
fprintf(stderr, "%s: Invalid pattern.\n", argv[1]);
return EXIT_FAILURE;
}
(void)regerror(result, &pattern, errmsg, length + 1);
fputs(errmsg, stderr);
fputc('\n', stderr);
return EXIT_FAILURE;
}
if (argc > 2) {
for (arg = 2; arg < argc; arg++) {
in = fopen(argv[arg], "rt");
if (!in) {
fprintf(stderr, "%s: %m.\n", argv[arg]);
return EXIT_FAILURE;
}
do_grep(in, argv[arg], &pattern, use_ansi);
if (ferror(in) || fclose(in)) {
fprintf(stderr, "%s: Read error.\n", argv[arg]);
return EXIT_FAILURE;
}
}
} else {
do_grep(stdin, "(standard input)", &pattern, use_ansi);
if (ferror(stdin)) {
fprintf(stderr, "Error reading from standard input.\n", argv[arg]);
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
|