Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах

Роббинс Арнольд

Шрифт:

42 }

43

44 if (optind == argc) /* проверка исправности */

45 usage;

46

47 compile_pattern(argv[optind]); /* компилировать шаблон */

48 if (errors) /* ошибка компиляции */

49 return 1;

50 else

51 optind++;

В строке 29 устанавливается значение

myname
, а строки 30–45 анализируют опции. Строки 47–51 компилируют регулярное выражение, помещая результаты в
pattern
,
compilе_раttern
увеличивает значение
errors
, если была проблема. (Соединение функций посредством глобальной переменной, как здесь, обычно считается плохой манерой. Для небольших программ, подобным этой, это сойдет, но для более крупных программ такое сопряжение может стать проблемой.) Если не было ошибок, строка 51 увеличивает значение
optind
так, что оставшиеся аргументы представляют файлы для обработки.

53 if (optind == argc) /* файлов нет, по умолчанию stdin */

54 process("standard input", stdin);

55 else {

56 /* цикл с файлами */

57 for (i = optind; i < argc; i++) {

58 if (strcmp(argv[i], "-") == 0)

59 process("standard input", stdin);

60 else if ((fp = fopen(argv[i], "r")) != NULL) {

61 process(argv[i], fp);

62 fclose(fp);

63 } else {

64 fprintf(stderr, "%s: %s: could not open: %s\n",

65 argv[0], argv[i], strerror(errno));

66 errors++;

67 }

68 }

69 }

70

71 regfree(&pattern);

72 return errors != 0;

73 }

Строки 53–69 обрабатывают файлы, отыскивая соответствующие шаблону строки. Строки 53–54 обрабатывают случай, когда файлы не указаны: программа читает со стандартного ввода. В противном случае, строки 57–68 обрабатывают в цикле файлы. Строка 58 обрабатывает особый случай '

', обозначающий стандартный ввод, строки 60–62 обрабатывают обычные файлы, а строки 63–67 обрабатывают ошибки.

75 /* compile_pattern --- компиляция шаблона */

76

77 void compile_pattern(const char *pat)

78 {

79 int flags = REG_NOSUB; /* информация о месте совпадения не требуется */

80 int ret;

81 #define MSGBUFSIZE 512 /* произвольно */

82 char error[MSGBUFSIZE];

83

84 if (ignore_case)

85 flags |= REG_ICASE;

86 if (extended)

87 flags |= REG_EXTENDED;

88

89 ret = regcomp(&pattern, pat, flags);

90 if (ret != 0) {

91 (void)regerror(ret, &pattern, error, sizeof error);

92 fprintf(stderr, "%s: pattern '%s': %s\n", myname, pat, error);

93 errors++;

94 }

95 }

Строки 75–95 определяют функцию

compile_pattern
. Она сначала устанавливает
REG_NOSUB
в
flags
, поскольку нам нужно знать лишь «подходит ли строка?», а не «где в строке располагается подходящий
текст?»

Строки 84-85 добавляют дополнительные флаги в соответствии с опциями командной строки. Строка 89 компилирует шаблон, а строки 90–94 сообщают о возникших ошибках

97 /* process --- читает строки текста и сопоставляет их с шаблоном */

98

99 void process(const char *name, FILE *fp)

100 {

101 char *buf = NULL;

102 size_t size = 0;

103 char error[MSGBUFSIZE];

104 int ret;

105

106 while (getline(&buf, &size, fp) != -1) {

107 ret = regexec(&pattern, buf, 0, NULL, 0);

108 if (ret != 0) {

109 if (ret != REG_NOMATCH) {

110 (void)regerror(ret, &pattern, error, sizeof error);

111 fprintf(stderr, "%s: file %s: %s\n", myname, name, error);

112 free(buf);

113 errors++;

114 return;

115 }

116 } else

117 printf("%s: %s", name, buf); /* вывести подходящие строки */

118 }

119 free(buf);

120 }

Строки 97–120 определяют функцию

process
, которая читает файл и выполняет сопоставление с регулярным выражением. Внешний цикл (строки 106–119) читает строки ввода. Для избежания проблем с длиной строки мы используем
getline
(см. раздел 3.2.1.9 «Только GLIBC: чтение целых строк:
getline
и
getdelim
»). Строка 107 вызывает
regexec
. Ненулевое возвращаемое значение означает либо неудачное сопоставление, либо какую-нибудь другую ошибку. Строки 109–115 соответственно проверяют
REG_NOMATCН
и выводят ошибку лишь тогда, когда возникла какая-нибудь другая проблема — неудачное сопоставление не является ошибкой

Если возвращаемое значение равно 0, строка совпала с шаблоном и соответственно строка 117 выводит имя файла и совпавшую строку.

122 /* usage --- вывод сообщения об использовании и выход */

123

124 void usage(void)

125 {

126 fprintf(stderr, "usage: %s [-i] [-E] pattern [ files ... ]\n", myname);

127 exit(1);

128 }

Функция

usage
выводит сообщение об использовании и завершает программу. Она вызывается, когда предоставлены недействительные аргументы или не предоставлен шаблон (строки 38–40 и 44–45).

Вот и все! Скромная, но тем не менее полезная версия

grep
в 130 строк кода.

12.9. Рекомендуемая литература

1. Programming Pearls, 2nd edition, by Jon Louis Bentley Addison-Wesley, Reading, Massachusetts, USA, 2000. ISBN- 0-201-65788-0. См. также веб-сайт этой книги. [131]

Проектирование программы с операторами проверки является одной из главных тем в этой книге.

131

http://www.cs.bell-labs.com/cm/cs/pearls/
Примеч. автора.

Поделиться:
Популярные книги

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

Иванов Дмитрий
12. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
В зоне особого внимания

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

Орлов Андрей Юрьевич
2. Бастард Императора
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Бастард Императора. Том 2

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1