我的输入日志是一个表单:
system 2018-02-05 04:15:49 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:52 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:53 :: aaaaaaaaaaaaa
system 2018-02-05 04:20:06 :: ccccccccccccc
system 2018-02-05 04:21:10 :: bbbbbbbbbbbbb
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:23:49 :: bbbbbbbbbbbbb
system 2018-02-05 04:23:49 :: ccccccccccccc
并希望用空行分隔每个时间块。 上述输入的预期输出为:
system 2018-02-05 04:15:49 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:52 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:53 :: aaaaaaaaaaaaa
system 2018-02-05 04:20:06 :: ccccccccccccc
system 2018-02-05 04:21:10 :: bbbbbbbbbbbbb
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:21:10 :: ccccccccccccc
system 2018-02-05 04:23:49 :: bbbbbbbbbbbbb
system 2018-02-05 04:23:49 :: ccccccccccccc
答案 0 :(得分:6)
我们的想法是形成每条线都是唯一的键,在您的情况下它是$2
和$3
(即在Awk的上下文第二和第三个空格分隔的列中)。
我们通过这种组合构建一个唯一键($2 $3
),如果此组合与后续行不同,则在解析行时,我们会打印一个新行字符(也由特殊变量ORS
表示或只在Awk中print ""
。以下代码仅反映了
$ awk '($2 $3)!=p && NR>1 {print ""} {print; p=($2 $3)}' file
system 2018-02-05 04:15:49 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
system 2018-02-05 04:15:51 :: aaaaaaaaaaaaa
...
答案 1 :(得分:4)
另一个简短的 awk
方法:
awk 'NR>1 && !a[$2$3]++{ print "" }1' file
!a[$2$3]++
- 使用 date $2
和 time {{1}的连接检查唯一 datetime 值} values as array key 输出:
$3
答案 2 :(得分:2)
每个时间块的另一个awk
方法
在您想要的时间间隔设置filter
。
#!/bin/bash
Year='$2'
Month='$2$3'
Day='$2$3$4'
Hour='$2$3$4$5'
Minute='$2$3$4$5$6'
Second='$2$3$4$5$6$7'
filter=$Second
awk -F'[ :-]' $filter'!=p{print ""}{p='$filter'}{print}' sys.log
答案 3 :(得分:1)
这可能适合你(GNU sed):
sed 'N;/^\(.*::\).*\n\1/!P;//!s/^[^\n]*//;P;D' file
在整个文件长度上保留一个两行窗口。如果第一行键与第二行不匹配,则打印第一行,然后删除其内容。始终打印下一行,然后删除并重复。如果第一行和第二行键不匹配,则第一行现在将为空,除了换行符。
反思,答案较短:
sed 'N;P;/^\(.*::\).*\n\1/D;s/^[^\n]*//;P;D' file
始终打印双行窗口的第一行。如果第一行和第二行中的键不同,请在第二行之前创建一个空行,打印,删除并重复。
答案 4 :(得分:0)
我还有一个使用bash for
循环和grep
的简单解决方案。不优雅(一旦输入文件太大,我认为相当慢),但它适用于问题上的示例:
IFS=$'\n'
for i in $(cut -d ' ' -f1-3 input_file.txt | sort -u)
do
grep $i input_file.txt
echo
done
IFS
更改确保for
循环将变量读取为行,而不仅仅是记录(请参阅更多here)。然后$i
变量存储前3个字段的唯一值,然后grep
存储在原始文件中,在每次迭代后引入一个空行echo
。我现在意识到这是两次读取input_file,但无论如何,希望它有所帮助。