単純なgrepコマンド
単純なgrep。引数で与えられた文字列にHITすると印字する。ただし-xオプションが与えられていれば逆に印字しない。また-nオプションでHITした行番号も印字する。オプションは-nxの書式も許可する。
以下はK&Rから。ただし分かりづらかったのでwhile文はfor文に変更した。
#include#include #define MAXLINE 1000 int getline(char *, int); int main(int argc, char *argv[]) { char line[MAXLINE]; long lineno; int c; int except = 0, number = 0, found = 0; /* オプション処理用のループ。 * 外側でコマンドラインの引数をインクリメントする。 * 内側でその引数の文字列処理を行う。 */ for (--argc, ++argv; argc > 0 && (*argv)[0] == '-'; --argc, ++argv) { for (++argv[0]; (c = *argv[0]); ++argv[0]) switch (c) { case 'x': except = 1; break; case 'n': number = 1; break; default: printf("find: illegal optinon %c\n", c); argc = 0; break; } } /* 引数が不正なら終了 */ if (argc != 1) { printf("Usage: find -x -n pattern\n"); return -1; } /* 印字処理用のループ。*/ for (lineno=1; getline(line, MAXLINE) > 0; ++lineno) { if ((strstr(line, *argv) != NULL) != except) { /* この処理はややこしい。 * 1. 文字列がHITし、かつexceptが0である * 2. 文字列がHITせず、かつexceptが1である * 上記2つの場合にprintする。*/ if (number) { printf("%ld:", lineno); } printf("%s", line); found++; } } return found; }
しかし、MAXLINEは1000なのに、linenoをlongで宣言しているのは何故だろう? 博士たちのご乱心かしら。
シンタックスシュガー
argv[i]は*(argv+i)のシンタックスシュガーで有ることを利用し、以下のように書き換えた。こちらの方が分かりやすいと思うのだけれど。
#include#include #define MAXLINE 1000 int getline(char *, int); int main(int argc, char *argv[]) { char line[MAXLINE]; long lineno; int c, i, j; int except, number, found; except = number = 0; for (--argc, i=1; argc > 0 && argv[i][0] == '-'; --argc, i++) { for (j=1; c = argv[i][j]; j++) switch (c) { case 'x': except = 1; break; case 'n': number = 1; break; default: printf("find: illegal optinon %c\n", c); argc = 0; break; } } if (argc != 1) { printf("Usage: find -x -n pattern\n"); return -1; } found = 0; for (lineno = 1; getline(line, MAXLINE) > 0; lineno++) { if ((strstr(line, argv[i]) != NULL) != except) { if (number) { printf("%ld:", lineno); } printf("%s", line); found++; } } return found; }