根据日期标签/时间戳拆分文本文件

Split text file basing on date tag / timestamp

我有包含日期​​标签的大日志文件。它看起来像这样:

[01/11/2015, 02:19]
foo
[01/11/2015, 08:40]
bar
[04/11/2015, 12:21]
foo
bar
[08/11/2015, 14:12]
bar
foo
[09/11/2015, 11:25]
...
[15/11/2015, 19:22]
...
[15/11/2015, 21:55]
...

等等。我需要将这些数据分成几天的文件,例如:

01.txt:

[01/11/2015, 02:19]
foo
[01/11/2015, 08:40]
bar

04.txt:

[04/11/2015, 12:21]
foo
bar

等我如何使用任何 unix 工具来做到这一点?

我不认为有一个工具可以在不进行少量编程的情况下完成这项工作,但是使用 Awk 进行少量编程真的不是那么难。

script.awk

/^\[[0-3][0-9]\/[01][0-9]\/[12][0-9]{3},/ {
    if ( != old_date)
    {
        if (outfile != "") close(outfile);
        outfile = sprintf("%.2d.txt", ++filenum); 
        old_date = 
    }
}
{ print > outfile }

第一个(较大的)代码块识别日期字符串,它也在 </code> 中(因此可以通过参考 <code> 使条件更精确,但它的好处很小到不存在)。在操作内部,它会检查日期是否与它记住的最后日期不同。如果是这样,它会检查它是否有打开的文件并在必要时关闭它(close 是 POSIX awk 的一部分)。然后它生成一个新的文件名,并记住它正在处理的当前日期。

第二个较小的块只是将当前行写入当前文件。

调用

awk -f script.awk data

假设您有一个文件script.awk;如果您愿意,可以将其作为脚本参数提供。如果全部封装在shell脚本中,我会使用表达式而不是第二个文件,但我发现使用文件开发更方便。 (shell 脚本将包含 awk '…the script…' "$@" 而没有单独的文件。)

示例输出文件

给定问题的样本数据,输出在五个文件中,01.txt .. 05.txt.

$ for file in 0?.txt; do boxecho $file; cat $file; done
************
** 01.txt **
************
[01/11/2015, 02:19]
foo
[01/11/2015, 08:40]
bar
************
** 02.txt **
************
[04/11/2015, 12:21]
foo
bar
************
** 03.txt **
************
[08/11/2015, 14:12]
bar
foo
************
** 04.txt **
************
[09/11/2015, 11:25]
...
************
** 05.txt **
************
[15/11/2015, 19:22]
...
[15/11/2015, 21:55]
...
$

boxecho 命令是一个简单的脚本,它在星号框中回应其参数:

echo "** $* **" | sed -e h -e s/./*/g -e p -e x -e p -e x

修改文件名格式

I wish have output as a [day].txt or [day].[month].[year].txt, based on date in file. Is that possible?

是;这是可能的,而且不是特别难。 split 函数是处理分解 </code> 中的值的一种方法。正则表达式指定方括号、斜杠和逗号是字段分隔符。 <code> 中的值有 5 个子字段:[ 之前的一个空字段,由斜线分隔的三个数字部分和 , 之后的一个空字段。数组名称 dmy 是组件存储顺序的助记符。

/^\[[0-3][0-9]\/[01][0-9]\/[12][0-9]{3},/ {
    if ( != old_date)
    {
        if (outfile != "") close(outfile)
        n = split(, dmy, "[/\[,]")
        outfile = sprintf("%s.%s.%s.txt", dmy[4], dmy[3], dmy[2])
        old_date = 
    }
}
{ print > outfile }

sprintf() 语句中的数字 4、3、2 排列成适合自己的顺序。给定的顺序是年、月、日,它有很多优点,包括它利用 ISO 8601 标准和文件自动按日期顺序排序。我强烈建议使用它,但你可以随心所欲。对于问题中显示的示例数据和输入,它生成的文件是:

2015.11.01.txt
2015.11.04.txt
2015.11.08.txt
2015.11.09.txt
2015.11.15.txt

这是我的想法。我使用 sed 命令和 awk 脚本。

$ cat biglog
[01/11/2015, 02:19]
foo
[01/11/2015, 08:40]
bar
[04/11/2015, 12:21]
foo
bar
aaa
bbb
[08/11/2015, 14:12]
bar
foo

$ cat sample.awk
#!/bin/awk -f

BEGIN {
  FS = "\n"
  RS = "\n\n"
}

{
  date = substr(, 2, 2)
  filename = date ".txt"

  for (i = 2; i <= NF; i++) {
    print $i >> filename
  }
}

使用方法

sed -e 's/^\(\[[0-9][0-9]\)/\n/' biglog | sed -e 1d | ./sample.awk

确认

ls *.txt
01.txt  04.txt  08.txt

$ cat 01.txt
foo
bar

$ cat 04.txt
foo
bar
aaa
bbb

$ cat 08.txt
bar
foo

还有一个awk

$ awk -F"[[/,]" -v d="." '/^[\[0-9\/, :\]]*$/{f= d  d  d"txt"} 
                                        {print [=10=]>f}' file

$ ls 20*
2015.11.01.txt  2015.11.04.txt  2015.11.08.txt  2015.11.09.txt  2015.11.15.txt

$ cat 2015.11.01.txt 
[01/11/2015, 02:19]
foo
[01/11/2015, 08:40]
bar