Bash 在每个时间块之间添加空行
我有一个输入日志表格:Bash 在每个时间块之间添加空行,bash,awk,sed,Bash,Awk,Sed,我有一个输入日志表格: 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 2
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
这样做的目的是形成一个键,使每一行都是唯一的,在您的例子中,它是
$2
和$3
(即在Awk的上下文中,以空格分隔的第二列和第三列)
通过这种组合,我们构建了一个唯一的键($2$3
),并且在解析行时,如果这种组合与后续行不同,我们将打印一个新行字符(也由特殊变量ORS
表示,或者仅在Awk中打印“)。下面的代码正好反映了这一点
$ 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
...
另一种简短的awk方法是:
awk 'NR>1 && !a[$2$3]++{ print "" }1' file
-使用日期![$2$3]+
和时间$2
值的串联作为数组键来检查唯一的日期时间值$3
输出:
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
这可能适用于您(GNU-sed):
在整个文件长度上保持两行窗口。如果第一行键与第二行键不匹配,请打印第一行,然后删除其内容。始终打印下一行,然后删除并重复。如果第一行和第二行键不匹配,则第一行现在将为空,但换行除外
经过深思熟虑,我给出了一个简短的回答:
sed 'N;P;/^\(.*::\).*\n\1/D;s/^[^\n]*//;P;D' file
始终打印两行窗口的第一行。如果第一行和第二行中的键不同,请在第二行前空行,打印、删除并重复。为每个时间段另一个
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
我有另一个简单的解决方案,使用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
循环将变量读取为行,而不仅仅是记录(请参阅更多)。然后,$i
变量存储前3个字段的唯一值,然后grep
返回原始文件,在每次迭代后引入一个带有echo
的空行。我现在意识到这是在两次读取输入文件,但无论如何,希望它能有所帮助。awk'{print$2,$3}'log | sort-u |同时读取a b;do awk-vv=“$a$b””$2$3==v”日志;回声;doneYou可以删除吗$2@TigerTV.ru对于这一特定数据段,是的,但很可能不是真实数据。“今天12:00:00”和“明天12:00:00”总是有可能的,我不明白。如果有“今天12:00:00”和“明天12:00:00”会怎么样?如果有两个连续的行,其中日期($2
)发生变化,但时间($2
)没有变化。哦,是的。谢谢。当它使用一个大日志时,内存使用会增加。@TigerTV.ru,那么不要将它用于“大日志”。这是我不使用的另一种方法,它只是对答案的补充。
IFS=$'\n'
for i in $(cut -d ' ' -f1-3 input_file.txt | sort -u)
do
grep $i input_file.txt
echo
done