【问题标题】:Regex to split columns of an Amazon S3 Bucket Log?正则表达式拆分 Amazon S3 存储桶日志的列?
【发布时间】:2011-12-19 03:58:39
【问题描述】:

我正在为我公司的 S3 存储桶设置 ETL 流程,以便我们可以跟踪我们的使用情况,但我在拆分 S3 日志文件的列时遇到了一些麻烦,因为 Amazon 使用空格、双引号和正方形括号来分隔列。

我在这个 SO 帖子中找到了这个正则表达式:[^\\s\"']+|\"([^\"]*)\"|'([^']*)'Regex for splitting a string using space when not surrounded by single or double quotes,这让我非常接近。我只需要帮助调整它以忽略单引号并忽略“[”和“]”之间的空格

这是我们文件之一的示例行:

dd8d30dd085515d73b318a83f4946b26d49294a95030e4a7919de0ba6654c362 ourbucket.name.config [31/Oct/2011:17:00:04 +0000] 184.191.213.218 - 013259AC1A20DF37 REST.GET.OBJECT ourbucket.name.config.txt "GET /ourbucket.name.config.txt HTTP/1.1" 200 - 325 325 16 16 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" -

格式定义如下:http://s3browser.com/amazon-s3-bucket-logging-server-access-logs.php

任何帮助将不胜感激!

编辑:响应 FailDev,输出应该是包含在两个方括号之间的任何字符串,例如[foo bar],两个引号,例如“foo bar”或空格,例如foo bar(其中 foo 和 bar 都将单独匹配。我已将示例行中的每个匹配项都分解为以下块中自己的行:

dd8d30dd085515d73b318a83f4946b26d49294a95030e4a7919de0ba6654c362 
ourbucket.name.config 
[31/Oct/2011:17:00:04 +0000] 
184.191.213.218 
- 
013259AC1A20DF37 
REST.GET.OBJECT 
ourbucket.name.config.txt 
"GET /ourbucket.name.config.txt HTTP/1.1" 
200 
- 
325 
325 
16 
16 
"-" 
"Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6" 
-

【问题讨论】:

  • 输出到底应该是什么?
  • 我不敢相信更多的人不需要这些信息!好问题,谢谢!

标签: c# java regex ssis


【解决方案1】:

这是我为解析节点中的 s3 日志文件而编写的一个愚蠢的正则表达式:

/^(.*?)\s(.*?)\s(\[.*?\])\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(\".*?\")\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(.*?)\s(\".*?\")\s(\".*?\")\s(.*?)$/

正如我所说,这是“愚蠢的” - 它在很大程度上依赖于他们不更改日志格式,并且每个字段不包含任何奇怪的字符。

【讨论】:

    【解决方案2】:

    您不能使用 string.split 来完成,您需要遍历“列”组的所有捕获(如果您使用的是 C#)

    This matches a non-quoted, non-bracketed field: [^\s\"\[\]]+
    This matches a bracketed field: \[[^\]\[]+\] 
    This matches a quoted field: \"[^\"]+\"
    

    在匹配过程中保留引号和括号是最简单的,然后使用 Trim('[','\','"') 将它们去掉。

    @"^((?<column>[^\s\"\[\]]+|\[[^\]\[]+\]|\"[^\"]+\")\s+)+$"
    

    【讨论】:

    • 谢谢,ORing 模式运行良好。此字符串模式最适合 C#:@"([^\s\""[]]+)|([[^][]+])|(\""[^\""]+\"") "
    • 谢谢。似乎堆栈溢出删除了我的斜线......我忘了将它嵌入代码块中。现在更新。
    【解决方案3】:

    这是一个 python 解决方案,可以帮助某人。它还会为您删除引号和方括号:

    import re
    log = '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be mybucket [06/Feb/2014:00:00:38 +0000] 192.0.2.3 79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be A1206F460EXAMPLE REST.GET.BUCKETPOLICY - "GET /mybucket?policy HTTP/1.1" 404 NoSuchBucketPolicy 297 - 38 - "-" "S3Console/0.4" -'
    
    regex = '(?:"([^"]+)")|(?:\[([^\]]+)\])|([^ ]+)'
    
    # Result is a list of triples, with only one having a value
    # (due to the three group types: '""' or '[]' or '')
    result = re.compile(regex).findall(log)
    for a, b, c in result:
        print(a or b or c)
    

    输出:

    79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be
    mybucket
    06/Feb/2014:00:00:38 +0000
    192.0.2.3
    79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be
    A1206F460EXAMPLE
    REST.GET.BUCKETPOLICY
    -
    GET /mybucket?policy HTTP/1.1
    404
    NoSuchBucketPolicy
    297
    -
    38
    -
    -
    S3Console/0.4
    -
    jon@jon-laptop:~/Downloads$ python regex.py
    79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be
    mybucket
    06/Feb/2014:00:00:38 +0000
    192.0.2.3
    79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be
    A1206F460EXAMPLE
    REST.GET.BUCKETPOLICY
    -
    GET /mybucket?policy HTTP/1.1
    404
    NoSuchBucketPolicy
    297
    -
    38
    -
    -
    S3Console/0.4
    -
    

    【讨论】:

      【解决方案4】:

      我同意@andy!考虑到 S3 的访问日志已经存在了多长时间,我不敢相信有更多人没有处理 S3 的访问日志。


      这是我使用的正则表达式

      /(?:([a-z0-9]+)|-) (?:([a-z0-9\.-_]+)|-) (?:\[([^\]]+)\]|-) (?:([0-9\.]+)|-) (?:([a-z0-9]+)|-) (?:([a-z0-9.-_]+)|-) (?:([a-z\.]+)|-) (?:([a-z0-9\.-_\/]+)|-) (?:"-"|"([^"]+)"|-) (?:(\d+)|-) (?:([a-z]+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:(\d+)|-) (?:"-"|"([^"]+)"|-) (?:"-"|"([^"]+)"|-) (?:([a-z0-9]+)|-)/i
      

      如果你使用的是 node.js,你可以利用我的模块让这更容易处理,或者将它移植到 C#,基本的想法都在那里。

      https://github.com/icodeforlove/s3-access-log-parser

      【讨论】:

        【解决方案5】:

        我尝试在 C# 中使用它,但发现上面的答案中有一些不正确的字符,并且您必须在末尾使用非引号、非括号字段的正则表达式,否则它匹配所有内容(使用 http://regexstorm.net/tester) :

        完整的正则表达式,首先是带括号的字段,第二个是带引号的字段,最后是不带引号的非括号字段:

        一个简单的 C# 实现:

            MatchCollection matches = Regex.Matches(contents, @"(\[[^\]\[]+\])|(""[^""]+"")|([^\s""\[\]]+)");
            for (int i = 0; i < matches.Count; i++)
            {
                Console.WriteLine(i + ": " + matches[i].ToString().Trim('[', ']', '"'));
            }
        

        【讨论】:

          【解决方案6】:

          这是我从AWS Knowledge Center 复制的正则表达式,并对其进行了一些修改以使其在 ASP.NET Core 中工作。

          new Regex("([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)");
          

          它对我们来说工作得很好。如果有人想使用c#类来存储访问日志,下面是解析日志文件的每一行并为其创建S3ServerAccessLog对象的代码。

          private List<S3ServerAccessLog> ParseLogs(string accessLogs)
          {
              // split log file per new line since each log will be on a single line.
              var splittedLogs = accessLogs.Split("\r\n", StringSplitOptions.RemoveEmptyEntries);
              var parsedLogs = new List<S3ServerAccessLog>();
          
              foreach (var logLine in splittedLogs)
              {
                  var parsedLog = ACCESS_LOG_REGEX.Split(logLine).Where(s => s.Length > 0).ToList();
                          
                  // construct 
                  var logModel = new S3ServerAccessLog
                  {
                      BucketOwner = parsedLog[0],
                      BucketName = parsedLog[1],
                      RequestDateTime = DateTimeOffset.ParseExact(parsedLog[2], "dd/MMM/yyyy:HH:mm:ss K", CultureInfo.InvariantCulture),
                      RemoteIP = parsedLog[3],
                      Requester = parsedLog[4],
                      RequestId = parsedLog[5],
                      Operation = parsedLog[6],
                      Key = parsedLog[7],
                      RequestUri = parsedLog[8].Replace("\"", ""),
                      HttpStatus = int.Parse(parsedLog[9]),
                      ErrorCode = parsedLog[10],
                      BytesSent = parsedLog[11],
                      ObjectSize = parsedLog[12],
                      TotalTime = parsedLog[13],
                      TurnAroundTime = parsedLog[14],
                      Referrer = parsedLog[15].Replace("\"", ""),
                      UserAgent = parsedLog[16].Replace("\"", ""),
                      VersionId = parsedLog[17],
                      HostId = parsedLog[18],
                      Sigv = parsedLog[19],
                      CipherSuite = parsedLog[20],
                      AuthType = parsedLog[21],
                      EndPoint = parsedLog[22],
                      TlsVersion = parsedLog[23]
                  };
          
                  parsedLogs.Add(logModel);
              }
          
              return parsedLogs;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-08-11
            • 1970-01-01
            • 1970-01-01
            • 2019-11-01
            • 1970-01-01
            • 2016-10-11
            • 2016-08-25
            • 1970-01-01
            相关资源
            最近更新 更多