如何处理最旧的文件到最新的bash?

时间:2015-06-02 06:07:48

标签: bash sed

概述

我有一堆日志文件,当它们达到一定大小时会翻转。日志文件中的每一行都有一堆记录器格式,然后是一些有趣的信息。我想获取这些文件并从每行的开头删除格式,然后将所有这些文件的输出放入一个文件中。然后,我将最终获取该文件并手动将其加载到另一个应用程序中。

详情

文件结构如下所示:

logs
 |-- modules
 |    +-- ...
 |-- application.log
 |-- gc.log
 |-- gc.log.1
 |-- ...
 +-- gc.log.10

因此logs包含子目录和多个日志文件。我感兴趣的是gc.log*

每个gc.log*文件在文件填满时会翻转到新文件。 gc.log始终是最新的,它最长为gc.log.10是最早的(默认情况下只有10,最高版本9,但这是可配置的。)

典型的gc.log*包含数千个条目,如:

INFO   | jvm 1    | 2015/05/28 04:40:58 | 1164752.977: [GC pause (young), 0.06583700 secs]
INFO   | jvm 1    | 2015/05/28 04:40:58 |    [Parallel Time:  45.2 ms]
INFO   | jvm 1    | 2015/05/28 04:40:58 |       [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
INFO   | jvm 1    | 2015/05/28 04:40:58 |        Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]
...

(是的,这些是来自Oracle JVM的G1 GC日志。我需要在单独的文件中使用这些,以便我可以使用GCViewer绘图)

一旦我删除了格式化,我需要它看起来像:

1164752.977: [GC pause (young), 0.06583700 secs]
   [Parallel Time:  45.2 ms]
      [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
       Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]

到目前为止我有什么

到目前为止,我已经了解到我不应该使用ls来获取文件。我在另一个问题上发现了这个问题(对不起,我忘了哪一个)Why you shouldn't parse the output of ls(1)

我使用以下内容列出文件,然后将它们从最旧到最新排序:

find "$logDir" -maxdepth 1 -type f -name 'gc.log*' | sort -Vr

这给了我以下内容:

./gc.log.10
./gc.log.9
./gc.log.8
./gc.log.7
./gc.log.6
./gc.log.5
./gc.log.4
./gc.log.3
./gc.log.2
./gc.log.1
./gc.log

我必须删除格式的命令是:

sed -e 's/^.\{7\}[|].\{10\}[|].\{21\}[|] //g'

(我可以使用cut -c43-

问题

我不确定如何将sort的输出转换为sed

当文件名(或$logDir)包含空格时,以下操作无效:

find "$logDir" -maxdepth 1 -type f -name 'gc.log*' | sort -Vr | xargs sed -e "s/^.\{7\}[|].\{10\}[|].\{21\}[|] //g"

我还需要从sed获取输出,然后将它们连接成一个文件。

问题

最后一个问题:

  • 如何以反向自然数排序顺序列出目录中的某些文件,从这些文件中每行的开头删除一个模式,最后将结果连接成一个文件(在bash中)?

3 个答案:

答案 0 :(得分:1)

由于你的文件名是固定的,你可以简单地使用大括号扩展:

for wrapper in wrapper.log{.{9..1},}; do
    echo "$wrapper"
    # do whatever you want to do...
done

出于您的目的,我想,这也可以起作用:

$ cat wrapper.log{.{9..1},} | sed ...

更通用的版本:

$ logfile="wrapper.log" # may contain spaces in filename
$ cat "$logfile"{.{9..1},} | sed ...

答案 1 :(得分:1)

在这种情况下,您的文件名非常简单,并且您对它们做的很少,我很想使用ls输出,假设您的文件具有直观的渐进式修改时间,那么所有的&# #39;需要的是:

ls -rt gc.? gc | xargs awk -F' [|] ' '{print $NF}' > newfile

例如:

$ cat gc
INFO   | jvm 1    | 2015/05/28 04:40:58 | 1164752.977: [GC pause (young), 0.06583700 secs]
INFO   | jvm 1    | 2015/05/28 04:40:58 |    [Parallel Time:  45.2 ms]
INFO   | jvm 1    | 2015/05/28 04:40:58 |       [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
INFO   | jvm 1    | 2015/05/28 04:40:58 |        Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]
$
$ cat gc.1
INFO   | jvm 1    | 2015/05/28 04:40:58 | 1234567.977: [GC pause (young), 0.06583700 secs]
INFO   | jvm 1    | 2015/05/28 04:40:58 |    [Parallel Time:  45.2 ms]
INFO   | jvm 1    | 2015/05/28 04:40:58 |       [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
INFO   | jvm 1    | 2015/05/28 04:40:58 |        Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]
$
$ cat gc.2
INFO   | jvm 1    | 2015/05/28 04:40:58 | 8889996.977: [GC pause (young), 0.06583700 secs]
INFO   | jvm 1    | 2015/05/28 04:40:58 |    [Parallel Time:  45.2 ms]
INFO   | jvm 1    | 2015/05/28 04:40:58 |       [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
INFO   | jvm 1    | 2015/05/28 04:40:58 |        Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]

$ ls -rt gc.? gc | xargs awk -F' [|] ' '{print $NF}'
8889996.977: [GC pause (young), 0.06583700 secs]
   [Parallel Time:  45.2 ms]
      [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
       Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]
1234567.977: [GC pause (young), 0.06583700 secs]
   [Parallel Time:  45.2 ms]
      [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
       Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]
1164752.977: [GC pause (young), 0.06583700 secs]
   [Parallel Time:  45.2 ms]
      [GC Worker Start (ms):  1164752977.7  1164752977.7  1164752977.7  1164752977.9
       Avg: 1164752977.8, Min: 1164752977.7, Max: 1164752977.9, Diff:   0.2]

答案 2 :(得分:1)

如果你想做得对(并且有GNU findsort),请告诉find写下以mtime开头的文件名,并用NUL字符分隔(唯一的字符是不能存在于UNIX上的文件的完全限定路径中;使用sort按mtime排序(而不是试图弄乱名字);然后阅读以下两段数据:

while IFS= read -r -d ' ' mtime && IFS= read -r -d '' filename; do
  sed -e 's/^.\{7\}[|].\{10\}[|].\{21\}[|] //g' <"$filename"
done < <(find "$logDir" -maxdepth 1 -type f -printf '%T@ %P\0' | sort -nz)

这将按照从最旧到最新的顺序处理文件。