我有一个具有以下日志格式的日志文件:
###<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
我如何按日期将此日志文件拆分为文件 YYYY_MM_DD.log?
答案1
一个perl
解决方案,利用 GNUdate
来转换日期:
perl -ne 'if(/^###<(.*)>/){
chomp($d=`date -d \"$1\" +%Y_%m_%d`);
$name="$d.log"
}
open(my $fh,">>","$name");
print $fh $_;' file.log
解释
-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
chomp
从结果中删除最后的换行符,以便date
我们稍后使用它。$name="$d.log"
date
:我们将命令 plus的结果保存.log
为变量$name
。open(my $fh,">>","$name");
$name
:以文件句柄的形式打开文件$fh
。如果您不知道文件句柄是什么,请不要担心,这只是意味着print $fh "foo"
将打印foo
到$name
。print $fh $_;
:将当前行打印到文件句柄指向的文件中$fh
。因此,将该行打印到当前保存为的任何文件中$name
。
答案2
解决此问题的一种方法是使用 awk。例如,以下命令:
awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file
应将文件拆分成文件,使用日期字段作为文件名
答案3
和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
可读形式:
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
/^#+<[^>]+>$/
{}
匹配包含日期的行,只有条件匹配时才会运行包围的块。如果匹配,我们将使用外部date
命令获取所需格式的日期并将输出保存在变量中file
,并将变量的内容保存lines
为文件file
(来自上一个块),然后lines
使用以下行再次实例化变量对于所有其他行,我们将这些行连接为变量
lines
最后一个块通过放入
END
块来保存