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