代码之家  ›  专栏  ›  技术社区  ›  JuMoGar

读取日志文件并以指定格式写入其他日志文件

  •  2
  • JuMoGar  · 技术社区  · 7 年前

    我有一个日志文本文件( *.txt )其中大约有250万条使用C语言的条目,我必须以特定格式读取并写入其他文件。

    202.32.92.47 - - [01/Jun/1995:00:00:59 -0600] "GET /~scottp/publish.html" 200 271 - -
    ix-or7-27.ix.netcom.com RFC-1413 John Thomas [01/Jun/1995:00:02:51 -0600] "GET /~ladd/ostriches.html" 200 205908 - "Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)" 
    ppp-4.pbmo.net - John Thomas [07/Dec/1995:13:20:28 -0600] "GET /dcs/courses/cai/html/introduction_lesson/index.html HTTP/1.0" 500 - "http://www.wikipedia.org/" "Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)" 
    ppp-4.pbmo.net - - [07/Dec/1995:13:20:37 -0600] "GET /dcs/courses/cai/html/index.html HTTP/1.0" 500 4528 - - 
    lbm2.niddk.nih.gov RFC-1413 - [07/Dec/1995:13:21:03 -0600] "GET /~ladd/vet_libraries.html" 200 11337 "http://www.wikipedia.org/" - 
    

    此日志(原始)文件的每行格式为: IP ID NAME [DATE:TIME TIMEZONE] "METHOD DIR" STATUS MB "WEB" "FROM" ||

    || ix-or7-27.ix.netcom.com || RFC-1413 || John Thomas || [01/Jun/1995 || :00:02:51 || -0600] || "GET || /~ladd/ostriches.html" || 200 || 205908 || - || "Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)" ||
    || ppp-4.pbmo.net || - || John Thomas || [07/Dec/1995 || :13:20:28 || -0600] || "GET || /dcs/courses/cai/html/introduction_lesson/index.html HTTP/1.0" || 500 || - || "http://www.wikipedia.org/" || "Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)" ||
    || ppp-4.pbmo.net || - || - || [07/Dec/1995 || :13:20:37 || -0600] || "GET || /dcs/courses/cai/html/index.html HTTP/1.0" || 500 || 4528 || - || - ||
    || lbm2.niddk.nih.gov || RFC-1413 || - || [07/Dec/1995 || :13:21:03 || -0600] || "GET || /~ladd/vet_libraries.html" || 200 || 11337 || "http://www.wikipedia.org/" || - ||
    

    例如,对于第一行:

    IP = ix-or7-27.ix.netcom.com 
    ID = RFC-1413 
    NAME = John Thomas 
    DATE = 01/Jun/1995
    TIME = 00:02:51 
    TIMEZONE = -0600 
    METHOD = GET 
    DIR: /~ladd/ostriches.html
    STATUS = 200 
    MB = 205908 
    WEB = -
    FROM = Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)
    

    (每个字段的值可以是 text - ).

    预期产出为:

    ix-or7-27.ix.netcom.com | RFC-1413 | John Thomas | 01/Jun/1995 | 00:02:51 | -06 | GET | /~ladd/ostriches.html | 200 || 205908 | - | Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5)
    ppp-4.pbmo.net | - | John Thomas || 07/Dec/1995 | 13:20:28 | -06 | GET | /dcs/courses/cai/html/introduction_lesson/index.html HTTP/1.0 | 500 | - | http://www.wikipedia.org/ | Mozilla/5.0 (X11; U; Linux i686; es-ES;rv:1.7.5) 
    ppp-4.pbmo.net | - | - || 07/Dec/1995 | 13:20:37 | -06 | GET | /dcs/courses/cai/html/index.html HTTP/1.0 | 500 || 4528 | - | - 
    lbm2.niddk.nih.gov | RFC-1413 || - | 07/Dec/1995 | 13:21:03 | -06 | GET | /~ladd/vet_libraries.html | 200 | 11337 | http://www.wikipedia.org/ | - 
    

    因此,格式是拆分原始行并添加 | 在每个字段之间。每个字段可以是:

    • 第二个参数(ID):捕获所有空间(可以是字符串或 )
    • 第三个参数(名称):catch all up to[(可以是带空格的字符串或 -
    • 第四个参数(日期):赶上 :
    • 第六个参数(时区):捕获所有到](-dddd必须在-dd中转换)
    • 第七个参数(方法):捕捉所有空间
    • 第十个参数(MB):捕捉所有空间
    • - )
    • )

    你知道我怎么能得到它吗?


    编辑1:

    我用于读取/写入文件的代码是:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main() {
        // variables
        int line[255];
        char *token;
    
        // open files
        FILE *fpr = fopen("myLogFile.txt","r");
        FILE *fpw = fopen("myFormattedLogFile.txt","w");
    
        // read file
        while (fgets(line, 255, fpr) != NULL) {
            token = strtok(line, " ");
            while (token != NULL) {
                // write file
                fprintf(fpw, "%s | ", token);
                token = strtok(NULL, " ");
            }
            fprintf(fpw, "\n");
        }
    
        // close files
        fclose(fpr);
        fclose(fpw);
    
        return 0;
    }
    

    John Thomas ,我不知道如何设置正确的格式(删除 [ ] , " ,更改数字格式,拆分日期和时间,控制是否为字符串或 - , ...).


    我有一个朋友:

    // 6º pattern. How can I recover it as string?
    // 7º pattern. How can I remove first "?
    // 8º patter. How can I remove last "?
    // how could catch all inside "" ? Which pattern should I use?
    // what is variable n?
    // what is Invalid_Input? It appears as undeclared
    

    解决方案更新后的代码为:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define LINE_LENGTH 255
    
    // First parameter (IP): catch all up to space
    #define IP_FMT "%s"
    char IP[LINE_LENGTH];
    
    // Second parameter (ID): catch all up to space (can be a string or a -)
    #define ID_FMT "%s"
    char ID[LINE_LENGTH];
    
    // Third parameter (NAME): catch all up to [ (can be a string with spaces or a -)
    #define NAME_FMT " %[^[]["
    char NAME[LINE_LENGTH];
    
    // Fourth parameter (DATE): catch all up to :
    #define DATE_FMT " %11[^:]:"
    char DATE[11+1];
    
    // Fifth parameter (TIME): catch all up to space
    #define TIME_FMT "%8s"
    char TIME[8+1];
    
    // Sixth parameter (TIMEZONE): catch all up to ] (-dddd must be converted in -dd)
    #define TIMEZONE_FMT "%5d]"
    int TIMEZONE;
    
    // Seventh parameter (METHOD): catch all up to space
    #define METHOD_FMT "%s"
    char METHOD[LINE_LENGTH];
    
    // Eigth parameter (DIR): catch all up to space
    #define DIR_FMT "%s"
    char DIR[LINE_LENGTH];
    
    // Ninth parameter (STATUS): catch all up to space
    #define STATUS_FMT "%s"
    char STATUS[LINE_LENGTH];
    
    // Tenth parameter (MB): catch all up to space
    #define MB_FMT "%s"
    char MB[LINE_LENGTH];
    
    // Eleventh parameter (WEB): catch all inside "" (or -)
    
    // Twelveth parameter (FROM): catch all inside "" (or -)
    
    
    
    int main() {
        // variables
        char *line = malloc(LINE_LENGTH);
        char *token;
        int position = 0;
    
        // open files
        FILE *fpr = fopen("log.txt","r");
        FILE *fpw = fopen("myFormattedLogFile.txt","w");
    
        // read file
        while (fgets(line, LINE_LENGTH, fpr) != NULL) {
    
            int n = 0; 
    
            sscanf
                (
                    line, 
                    IP_FMT ID_FMT NAME_FMT DATE_FMT TIME_FMT TIMEZONE_FMT METHOD_FMT DIR_FMT STATUS_FMT MB_FMT " %n", 
                    IP, ID, NAME, DATE, TIME, &TIMEZONE, METHOD, DIR, STATUS, MB, &n
                ); 
    
            NAME[strlen(NAME)-1] = '\0';
    
            fprintf
                (
                    fpw, 
                    "%s | %s | %s | %s | %s | %d | %s | %s | %s | %s\n", 
                    IP, ID, NAME, DATE, TIME, TIMEZONE, METHOD, DIR, STATUS, MB
                );
    
        }
    
        // close files
        fclose(fpr);
        fclose(fpw);
    
        return 0;
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   chux    7 年前

    sscanf() "%n" 我能胜任这项工作。可能需要一些后期处理,如 NAME .

    // First parameter (IP): catch all up to space
    #define IP_FMT "%s"
    char IP[sizeof line];
    
    // Second parameter (ID): catch all up to space (can be a string or a -)
    #define ID_FMT "%s"
    char ID[sizeof line];
    
    // Third parameter (NAME): catch all up to [ (can be a string with spaces or a -)
    #define NAME_FMT " %[^[]["
    char NAME[sizeof line];
    
    // Fourth parameter (DATE): catch all up to :
    #define DATE_FMT " %11[^:]:"
    char DATE[11+1];
    
    // Fifth parameter (TIME): catch all up to space
    #define TIME_FMT "%8s"
    char TIME[8+1];
    
    // Sixth parameter (TIMEZONE): catch all up to ] (-dddd must be converted in -dd)
    #define TIMEZONE_FMT "%5d]"
    int TIMEZONE;
    
    // Other fields left for OP
    
    int n = 0;
    sscanf(s, IP_FMT ID_FMT NAME_FMT DATE_FMT TIME_FMT " %n", 
        ID, ID, NAME, DATE, TIME, &TIMEZONE, &n);
    
    if (n == 0) return Invalid_Input;
    trim(NAME);