Unix 經典工具 grep 的極簡實現:從標準輸入逐行讀取,輸出包含指定模式字符串的行。核心 API:fgets/getline 讀行,strstr 子串匹配。代碼 < 25 行,演示流處理與字符串查找基礎。
#include#include #define MAXLINE 1000 // 讀取一行(含換行符),返回長度,EOF 返回 0 int my_getline(char *line, int max) { int c, i; for (i = 0; i < max - 1 && (c = getchar()) != EOF && c != '\n'; i++) line[i] = c; if (c == '\n') line[i++] = c; line[i] = '\0'; return i; } int main(int argc, char *argv[]) { char line[MAXLINE]; int found = 0; if (argc != 2) { fprintf(stderr, "用法: %s 模式\n", argv[0]); return 1; } while (my_getline(line, MAXLINE) > 0) { if (strstr(line, argv[1]) != NULL) { printf("%s", line); // line 已含換行 found++; } } return found; // 返回匹配行數作為退出碼(0=無匹配) }
my_getline:手寫讀行函數,處理 EOF、\n、緩衝區上限,返回長度便於判斷空行。strstr(haystack, needle):標準庫子串查找,返回首次出現位置或 NULL。argv[1] 為命令行傳入的搜索模式(字面字符串,非正則)。0 無匹配,>0 匹配行數,符合 Unix 約定(grep 退出碼 0=找到,1=未找到,2=錯誤;此處簡化)。gcc mini_grep.c -o mygrep echo -e "apple\nbanana\ncherry" | ./mygrep an # 輸出: # banana ./mygrep "error" < log.txt # 文件輸入 dmesg | ./mygrep "USB" # 管道過濾
regex.h (regcomp/regexec) 支持 POSIX 正則。argv[2...],打印文件名前綴。-i 忽略大小寫、-n 顯示行號、-v 反向匹配、-c 計數。mmap + memmem 或 Boyer-Moore 算法。mini grep 是「行過濾器」模式的教科書實現:**流式讀取 + 謂詞判斷 + 輸出**。掌握此模式,可快速構建 awk、sed、日誌分析器等流處理工具。C 語言標準庫 stdio.h + string.h 足以支撐核心邏輯,體現 Unix 哲學「小而專、組合強」。