使用C语言提取日志中指定CODE多段内容的实现方案咨询
C语言解析日志提取指定CODE段落的解决方案
核心思路
日志段落有明确的起止标记,按段落为单位处理是最高效的方式,能避免逐行匹配时的跨内容问题:
- 遍历日志文件,每次定位到
----- start -----标记,记录该段落的起始位置 - 从起始位置开始读取内容,直到遇到
----- end -----标记,期间检查是否包含目标CODE(比如CODE: 1111) - 如果当前段落包含目标CODE,就将整个段落(从start到end的所有内容)提取输出;如果不包含,直接跳过该段落,继续寻找下一个start标记
代码实现示例
#include <stdio.h> #include <string.h> #define BUF_SIZE 1024 #define START_MARK "----- start -----" #define END_MARK "----- end -----" int extract_log_by_code(FILE *fp, const char *target_code) { char buf[BUF_SIZE]; fpos_t start_pos; int found_code = 0; // 循环寻找每个段落的起始标记 while (fgets(buf, BUF_SIZE, fp) != NULL) { // 找到段落起始 if (strstr(buf, START_MARK) != NULL) { // 修正并记录段落起始位置(fgets已读走start行,需回退到行首) fseek(fp, -strlen(buf), SEEK_CUR); fgetpos(fp, &start_pos); found_code = 0; // 读取当前段落内容,直到end标记 while (fgets(buf, BUF_SIZE, fp) != NULL) { // 检查是否包含目标CODE if (strstr(buf, target_code) != NULL) { found_code = 1; } // 遇到段落结束标记 if (strstr(buf, END_MARK) != NULL) { if (found_code) { // 回退到段落起始,输出整个段落 fsetpos(fp, &start_pos); while (fgets(buf, BUF_SIZE, fp) != NULL) { fputs(buf, stdout); if (strstr(buf, END_MARK) != NULL) { break; } } // 若只需第一个匹配段落,取消下面的return注释 // return 0; } break; // 跳出当前段落读取循环 } } } } return 1; } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <log_file> <target_code>\n", argv[0]); return 1; } FILE *fp = fopen(argv[1], "r"); if (fp == NULL) { perror("Failed to open log file"); return 1; } extract_log_by_code(fp, argv[2]); fclose(fp); return 0; }
关键细节说明
- 用
fgetpos/fsetpos精准定位段落起始,避免fseek因文本文件换行符差异导致的定位错误 - 段落内逐行检查CODE,无需单独处理跨多行的DESC,只要CODE在当前段落内,就提取整个段落
- 代码支持提取所有匹配的段落,若只需要第一个匹配,取消
return 0的注释即可 - 处理了
fgets读取start标记行后的位置修正,确保能完整输出整个段落
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

