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

如何处理从最旧到最新的bash文件?,bash,sed,Bash,Sed,概述 我有一堆日志文件,当它们达到一定大小时会滚动。日志文件中的每一行都有一组记录器格式,然后是一些有趣的信息。我想将这些文件从每一行的开头删除格式,然后将所有这些文件的输出放在一个文件中。然后,我最终会将该文件手动加载到另一个应用程序中 详细信息 文件结构如下所示: logs |-- modules | +-- ... |-- application.log |-- gc.log |-- gc.log.1 |-- ... +-- gc.log.10 因此,日志包含子目录和

概述

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

详细信息

文件结构如下所示:

logs
 |-- modules
 |    +-- ...
 |-- application.log
 |-- gc.log
 |-- gc.log.1
 |-- ...
 +-- gc.log.10
因此,
日志
包含子目录和多个日志文件。我安装的是
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
来获取文件。我在另一个SO问题上发现了这一点(对不起,我忘了是哪一个)

我使用以下方法列出文件,然后将其从最旧到最新排序:

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中)

由于文件名是固定的,您只需使用大括号扩展即可:

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 ...

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

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]

如果您想正确操作(并让GNU
find
sort
),请告诉
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)
而IFS=read-r-d''mtime&&IFS=read-r-d''文件名;做

sed-e的//^.{7\}[|].{10\}[|].{21\}[|]//g'您有GNU
查找
?如果是这样的话,我们可以使用
-printf
将修改时间放入输出中,假设这确实是您想要排序的。顺便说一句,写一篇文章而不是一个孤立的问题(或两个或三个问题)有点不理想。其他人希望能够在shell脚本中按mtime安全地对任意命名的文件进行排序的可能性非常非常高,因此,如果一个问题只问这个问题(如果这个主题上还没有),就会得到大量的视图/投票/答案。询问如何同时完成A、B和C,意味着你会得到一个答案只对你有用的问题,因为几乎没有人会有完全相同的文件格式&C。@EdMorton抱歉,这是一个复制粘贴错误。我在测试期间重命名了它们。我已经更新了问题。@charlesduff感谢您的反馈。我这样做只是因为我读了一些其他问题,每个人都想要实际的用例,而不是OP认为他们想要在一个人为的例子中做什么。这是一个平衡的行为,可以肯定。啊,我以前从未见过支架扩展。似乎它可以工作,但我遗漏的是,文件的数量是可配置的。默认情况下只有10个(最多9个版本),但情况可能并非总是如此。对于未来的读者,
wrapper.log
=
gc.log
(有一个复制粘贴错误已在问题中修复)。@EdMorton是的,我同意,对不起。我在测试时遇到了这个问题,因此我使用了
sort-Vr
,但忘记了更新问题。我想我会使用类似的东西,因为它很容易理解。似乎不能处理空格,但现在还可以。虽然我目前正在使用我的
find
方法,而不是
ls
,并且它正在做这项工作(实际上时间戳可能还可以,但对于测试,我是按各种顺序创建的)。