2

我目前正在尝试清理一些日志文件,以便它们具有更易于阅读的格式,并且一直在尝试使用 gnu cut 命令,该命令效果很好,尽管我真的想不出删除 [INFO] 的好方法字符串的一部分

logs/logs/server_1283258036.log:2010-08-31 23:06:51 [INFO] <NateMar> where?!
logs/logs/server_1281904775.log:2010-08-15 22:59:53 [INFO] <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh
logs/logs/server_1282136782.log:2010-08-18 16:27:32 [INFO] <pinguin> <pinguin>§F :/
logs/logs/server_1282136782.log:2010-08-18 16:27:37 [INFO] <TotempaaltJ> <TotempaaltJ>§F That helped A LOT
logs/logs/server_1282136782.log:2010-08-18 16:27:37 [INFO] <Rizual> §b<Rizual>§F hm?
logs/logs/server_1282136782.log:2010-08-18 16:29:10 [INFO] <pinguin> <pinguin>§F bah
logs/logs/server_1282136782.log:2010-08-18 16:29:35 [INFO] <TotempaaltJ> <TotempaaltJ>§F Finished my houses 
logs/logs/server_1282136782.log:2010-08-18 16:29:40 [INFO] <TotempaaltJ> <TotempaaltJ>§F or whatever
logs/logs/server_1282136782.log:2010-08-18 16:30:47 [INFO] <Rizual> §b<Rizual>§So much iron
logs/logs/server_1282136782.log:2010-08-18 16:30:58 [INFO] <TotempaaltJ> <TotempaaltJ>§F Ah yes, furnaces don't work.o
logs/logs/server_1282136782.log:2010-08-18 16:31:01 [INFO] <Rizual> §b<Rizual>§F They do
logs/logs/server_1282136782.log:2010-08-18 16:31:06 [INFO] <TotempaaltJ> <TotempaaltJ>§F Hm
logs/logs/server_1282136782.log:2010-08-18 16:31:08 [INFO] <Rizual> §b<Rizual>§F just need to use /lighter
logs/logs/server_1282136782.log:2010-08-18 16:31:12 [INFO] <Valrix> <Valrix>§FNotch fixed them?

我最终希望将字符串简化为类似于以下内容的内容(请记住,日志有两种格式,旧格式有两个名称副本,如上面的大部分日志中所示,还有更新的格式,其中只有一次名称(可以在第一个日志行中看到<natemar>))

2010-08-31 23:06:51 <NateMar> where?!    
2010-08-15 22:59:53 <BoonTheMoon> ohhhhhh (this one would require both the same editing as above, plus removal of the "extra" name §b<BoonTheMoon>§)    

我该怎么做呢?考虑过使用 awk,尽管我很难掌握它的工作原理,所以不知道如何设置一些东西来做到这一点。任何帮助将不胜感激,谢谢!

4

4 回答 4

3

您使用该cut命令走在正确的轨道上。删除 [INFO] 字段的关键是将其从最终输出中排除。该 -f1,2,4-参数通过包含第 3 个字段之外的所有字段来实现这一点,此时只是 [INFO]。

cut -d: -f2- Input.txt | cut -d' ' -f1,2,4- > Output.txt    
于 2012-09-10T00:33:50.857 回答
3

在 sed、awk 和 bash 中对此进行了更多说明:

[ghoti@pc ~]$ cat text
logs/logs/server_1283258036.log:2010-08-31 23:06:51 [INFO] <NateMar> where?!
logs/logs/server_1281904775.log:2010-08-15 22:59:53 [INFO] <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

[ghoti@pc ~]$ sed 's/^[^:]*://;s/[[][^]]*[]] //' text
2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

[ghoti@pc ~]$ awk '{sub(/^[^:]+:/,""); $3=""} 1' text
2010-08-31 23:06:51  <NateMar> where?!
2010-08-15 22:59:53  <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

[ghoti@pc ~]$ while read line; do line=${line#*:}; echo "${line/\[*\] }"; done < text
2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

虽然这些很简单,但为了简短起见,它们可能并不完美。例如,awk 脚本通过删除第三个“单词”,留下分隔现在为空的单词的空格。

请注意,由于单行代码可能看起来很“优雅”,因此对于快速工作来说,明确代码通常是一个更好的主意,尤其是当您必须处理未知的输入数据或者您不会在之后立即检查结果时你运行的东西。

这更难阅读,但可能更安全,具体取决于您的输入:

[ghoti@pc ~]$ awk '$3~/^[[].+[]]$/{$3="";sub(/  /," ")} {sub(/^[^:]+:/,"")} 1' text
2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> çb<BoonTheMoon>çohhhhhh

对于 bash 脚本,使用字符类而不是 glob 会更安全:

[ghoti@pc ~]$ shopt -s extglob
[ghoti@pc ~]$ while read line; do line=${line#*:}; echo "${line/\[+([[:upper:]])\] /}"; done < text
2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> çb<BoonTheMoon>çohhhhhh

请注意,extglobshopt 选项允许您在参数替换模式中使用更高级的模式匹配。 man bash并寻找Pathname Expansion细节。

更新:

您为您的问题添加了一个最初不存在的新要求。以下是使用 awk 实现新要求的方法:

awk '$3~/^[[].+[]]$/{$3="";sub(/  /," ")} {sub(/^[^:]+:/,"")} $3~/^<.+>$/{sub(/^(§b)?<[[:alpha:]]+>§/,"",$4)} 1' text

如果第三个字符串看起来像括号中的昵称,这只是从第四个字符串中删除彩色昵称。这适用于您发布的示例,但只有您可以确定这是否适合您。

并与 bash:

shopt -s extglob
while read date time tag nick line; do
  printf "%s %s %s %s\n" "${date#*:}" "$time" "$nick" "${line/#*([^< ])$nick??}"
done < text
于 2012-09-10T01:41:22.550 回答
2

(根据对上述评论中发布的问题的回答,可能有待修订)

使用awk

awk '{sub(".log:", ".log "); print $2, $3, $5, $6}' data.txt

会给你:

2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

说明

我将:后面的“ .log:”更改为空白,然后能够用空格分隔行中的字段。您感兴趣的字段是 2、3、5 和 6,所以我awk通过使用$来打印它们以获取行中每个字段的内容。

请注意,printf如果需要,您还可以使用它来更精确地格式化数据。

于 2012-09-09T21:36:17.207 回答
1

有了sed它可以更直观地完成:

$> cat ./text
logs/logs/server_1283258036.log:2010-08-31 23:06:51 [INFO] <NateMar> where?!
logs/logs/server_1281904775.log:2010-08-15 22:59:53 [INFO] <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

$> sed -r -e 's/^.*log:([0-9]{4}-[0-9]{2}-[0-9]{2}\ )([0-9\ \:]*\ )(\[[A-Z]*\]\ )(.*)$/\1\2\4/' ./text
2010-08-31 23:06:51 <NateMar> where?!
2010-08-15 22:59:53 <BoonTheMoon> §b<BoonTheMoon>§ohhhhhh

整个想法是匹配日志字符串的某些字段,然后只留下您需要的字段。

于 2012-09-09T21:55:52.907 回答