У меня есть файл журнала с этим форматом журнала:
###<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?
Один подход для решения этого мог быть должен использовать awk. Например, эта команда:
awk -F'[ <,]+' '/^###/{close(f);f=$4"_"$2"_"$3".log"}{print >> f}END{close(f)}' file
должен разделить файл на файлы, с помощью полей даты в качестве имен файлов
A perl
решение, используя в своих интересах GNU date
преобразовать даты:
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(/^###<(.*)>/)
: если строка запускается с ###<
, получите все между <>
как $1
(это - то, что круглые скобки делают).chomp($d=
дата-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
команда плюс .log
как переменная $name
. open(my $fh,">>","$name");
: откройте файл $name
как дескриптор файла $fh
. Не волнуйтесь, не знаете ли Вы, каков дескриптор файла, это просто означает это print $fh "foo"
распечатает foo
в $name
.print $fh $_;
: распечатайте текущую строку в файл что дескриптор файла $fh
точки к. Так, распечатайте строку в то, что в настоящее время сохраняется как $name
.С 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
блок