0

我有以下日志

   06-09-2013 14:22:33 127.0.0.1 - 127.0.0.1 80 GET 304 207 410 HTTP/1.1 127.0.0.1 Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0 cs_vi=- cs_uuid=- cs_si=- http://clickstream.local/

如何将日志拆分为字段。我曾尝试过,log.split(" ")因为用户代理之间包含空间,所以它的工作方式不同。

我正在搜索问题,所以我知道可以使用正则表达式。

Anyregex按字段拆分日志。

输出可以

06-09-2013, 14:22:33, 127.0.0.1, etc

任何想法都会很棒。

4

3 回答 3

1

如果此日志是使用生成的,Apache我建议更改LogFormat以使字符串更适合解析。但是,更改此选项可能不是一种选择。

我下面的两个建议期望日志字符串在日志参数数量方面看起来相同。

第一个选择是使用这个例子,它不包含那么多regexp但更干净。不过可能会很慢。

public class RunMe {

    public static final int AGENT_INFO_START=12;

    public static void main(String[] args) {

        int i=0;
        StringBuffer logElement = new StringBuffer();
        ArrayList<String> logElements = new ArrayList<String>();
        String string = new String("06-09-2013 14:22:33 127.0.0.1 - 127.0.0.1 80 GET 304 207 410 HTTP/1.1 127.0.0.1 Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0 cs_vi=- cs_uuid=- cs_si=- http://clickstream.local/");         

        String[] elements = string.split("\\s");
        for(String element : elements) {
            logElement.append(element);
            i++;
            if(i > AGENT_INFO_START && i < elements.length-4) {
                logElement.append(" ");
            } else {
                logElements.add(logElement.toString());
                logElement.setLength(0);
            }

        }

        for(String element : logElements) {
            System.out.println("Field: " + element);
        }
    }
}

我想regexp这会使代码有点难以理解,因为我绝不是一个好的正则表达式生成器,所以很可能有regexp比这个更好的。

public class RunMe {
    public static void main(String[] args) {

        StringBuffer logElement = new StringBuffer();
        ArrayList<String> logElements = new ArrayList<String>();
        String string = new String("06-09-2013 14:22:33 127.0.0.1 - 127.0.0.1 80 GET 304 207 410 HTTP/1.1 127.0.0.1 Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0 cs_vi=- cs_uuid=- cs_si=- http://clickstream.local/");

        // Put "" around all fields.
        String newStr = string.replaceAll("^([0-9-]*)\\s([0-9:]*)\\s([0-9\\\\.]*)\\s(-)\\s([0-9\\\\.]*)\\s([0-9]*)\\s(GET|POST)\\s([0-9]*)\\s([0-9]*)\\s([0-9]*)\\s([a-zA-Z0-9\\\\./]*)\\s([0-9\\\\.]*)\\s(.*)\\s(cs_vi=.*)\\s(cs_uuid=.*)\\s(.*)\\s(.*)", 
                                            "\"$1\" \"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\" \"$9\" \"$10\" \"$11\" \"$12\" \"$13\" \"$14\" \"$15\" \"$16\" \"$17\"");

        String[] elements = newStr.split("\"");
        for(String element : elements) {
            System.out.println(element);
        }
    }
}
于 2013-09-09T14:11:42.667 回答
0

尝试

/(\d\d-\d\d-\d\d\d)\s(\d\d:\d\d:\d\d)\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s(\d+)\s((:?GET)|(:?POST))\s(\d{3})\s(\d{3})\s(\d{3})\s([^ ]+)\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s(.+)\s(cs_vi[^ ]+)\s(cs_si[^ ]+)\s(.+)$/

这应该提取字段。但我不能 100% 确定它是否正确,因为我不知道你的日志文件的确切格式,我只是根据你提供的样本工作。

于 2013-09-06T13:02:33.717 回答
-1

您可以使用反向引用的概念!

这很简单。只需为日志文件和要捕获的每个字段编写一个正则表达式,将正则表达式的模式部分放在括号中:()。这会创建一个反向引用,您可以使用反向引用从正则表达式中创建一个新字符串。

为您的日志:

将日志条目读入 String 变量,然后使用 string.split("regex");

例如:

如果您的日志是

 06-09-2013 14:22:33 127.0.0.1 - 127.0.0.1 80 GET

您的代码将如下所示:

String string = " 06-09-2013 14:22:33 127.0.0.1 - 127.0.0.1 80 GET";
String regex = "(/d+\-/d+\-\d+)\s?(\d+\:\d+\:\d+)\s?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s?\s?(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s?(\d+)\s?(\w+)";
string.split(regex);

希望这可以帮助

于 2013-09-06T13:10:03.493 回答