按日期拆分日志文件

tm4*_*4ig 7 sed awk text-processing

我有一个具有这种日志格式的日志文件:

###<Aug 8, 2016 11:59:05 PM>
different text
...
different text
###<Aug 15, 2016 9:10:55 AM>
different text
...
...
...
different text
###<Aug 22, 2016 10:02:17 PM>
different text
...
...
...
...
different text
###<Sep 1, 2016 1:00:01 AM>
different text
###<Sep 7, 2016 3:00:01 PM>
different text
...
...
different text
Run Code Online (Sandbox Code Playgroud)

如何按日期将此日志文件拆分为文件 YYYY_MM_DD.log?

ter*_*don 7

一个perl解决方案,利用 GNUdate转换日期:

perl -ne 'if(/^###<(.*)>/){
            chomp($d=`date -d \"$1\" +%Y_%m_%d`);
            $name="$d.log"
          } 
          open(my $fh,">>","$name"); 
          print $fh $_;' file.log 
Run Code Online (Sandbox Code Playgroud)

解释

  • -ne: 逐行读取输入文件(将每一行保存为特殊变量$_)并将给出的脚本应用-e到每一行。
  • if(/^###<(.*)>/): 如果该行以 开头###<,则捕获<>as之间的所有内容$1(这就是括号的作用)。
  • chomp($d=date -d \"$1\" +%Y_%m_%d );date命令重新格式化日期。例如:

    $ date -d "Sep 1, 2016 1:00:01 AM" +%Y_%m_%d
    2016_09_01
    
    Run Code Online (Sandbox Code Playgroud)

    chomp去除的结果最后的换行符date,所以我们以后可以使用它。

  • $name="$d.log":我们将date命令加号的结果保存.log为变量$name
  • open(my $fh,">>","$name");: 打开文件$name作为文件句柄$fh。如果您不知道文件句柄是什么,请不要担心,这只是意味着print $fh "foo"它将打印foo$name.
  • print $fh $_;: 将当前行打印到文件句柄$fh指向的文件中。因此,将该行打印到当前保存为$name.


use*_*001 6

解决此问题的一种方法可能是使用 awk。例如,这个命令:

awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file
Run Code Online (Sandbox Code Playgroud)

应该将文件拆分为文件,使用日期字段作为文件名


hee*_*ayl 6

awk

awk '/^#+<[^>]+>$/ {if (lines) print lines >file; \
     dt=gensub("^#+<([^>]+)>$", "\\1", $0)
     dt_cmd="date -d \""dt"\" +%Y_%m_%d.log" \
     dt_cmd | getline file; lines=$0; next}; \
     {lines=lines ORS $0} END {print lines >file}' file.log
Run Code Online (Sandbox Code Playgroud)

可读形式:

awk '
      /^#+<[^>]+>$/ {
                    if (lines) 
                        print lines >file
                    dt=gensub("^#+<([^>]+)>$", "\\1", $0)
                    dt_cmd="date -d \""dt"\" +%Y_%m_%d.log"
                    dt_cmd | getline file; lines=$0
                    next
                    }
      {
      lines=lines ORS $0
      } 
      END {
          print lines >file
          }' file.log
Run Code Online (Sandbox Code Playgroud)
  • /^#+<[^>]+>$/匹配包含日期的行,被包围的块{}只会在条件匹配时运行。如果匹配,我们将通过使用外部date命令获取所需格式的日期并将输出保存在变量中file,并将变量的内容保存lines为文件file(来自前一个块),然后lines使用行再次实例化变量

  • 对于所有其他行,我们将这些行连接为变量 lines

  • 通过放入块保存最后一个END