合并在sed之间并且不包括重复模式的行

时间:2017-05-10 11:19:48

标签: regex awk sed

我有一个包含时间戳的行数的文件,中间有几行。例如,

TIMESTAMP MESSAGE
TRAIL 1
TRAIL 2
TIMESTAMP MESSAGE2
TRAIL 21
TRAIL 22 ...

我想将所有跟踪消息添加到一行中,或者更好的是将两个时间戳之间的所有行添加到一行中,以便我的输出看起来像

TIMESTAMP MESSAGE TRAIL 1 TRAIL 2
TIMESTAMP MESSAGE2 TRAIL 21 TRAIL 22 ...

我在这里遇到的几个问题很相似,但在我的案例中都没有。我尝试使用

sed -i '/pattern_for_timestamp/{n;:l N;/pattern_for_timestamp/b ; s/\n// ; bl}'

但它只会更改模式的每个替代事件。跟踪消息中不需要任何模式。在这种情况下,我更倾向于使用sedawk

4 个答案:

答案 0 :(得分:3)

使用gawk,您可以使用正则表达式作为记录分隔符,然后使用(仅限gawk)内置RT来恢复其输出值:

$ cat file
20170102 MESSAGE
TRAIL 1
TRAIL 2
20170312 MESSAGE2
TRAIL 21
TRAIL 22
20170527 MESSAGE3
TRAIL 31
TRAIL 32

$ gawk -v RS="[0-9]{8}" 'NR>1{gsub("\n", " "); print ts $0} {ts=RT}' file
20170102 MESSAGE TRAIL 1 TRAIL 2 
20170312 MESSAGE2 TRAIL 21 TRAIL 22 
20170527 MESSAGE3 TRAIL 31 TRAIL 32 

答案 1 :(得分:2)

我会收集保留空间中的行直到它们完成,然后修改和打印,例如:

parse.sed

/^TIMESTAMP/ b prn            # Run the prn subroutine
H                             # Anything else is appended to hold-space
$ b prn                       # Also run prn at end-of-input
b                             # Process next line

:prn
x                             # Swap pattern-space and hold-space
s/\n/ /g                      # Replace \n with space
1!p                           # Print the result if not on the first line

像这样运行:

sed -nf parse.sed infile

或者作为一个单行:

sed -n '/^TIMESTAMP/bp;H;$bp;b;:p;x;s/\n/ /g;1!p' infile

输出:

TIMESTAMP MESSAGE TRAIL 1 TRAIL 2
TIMESTAMP MESSAGE2 TRAIL 21 TRAIL 22 ...

答案 2 :(得分:1)

这是我在awk中的尝试:

awk '/^TIMESTAMP/{ if (NR > 1){ ORS = ""; print "\n"} ORS = " " };1' file

输出:

TIMESTAMP MESSAGE TRAIL 1 TRAIL 2
TIMESTAMP MESSAGE2 TRAIL 21 TRAIL 22

答案 3 :(得分:1)

这可能适合你(GNU sed):

sed ':a;N;/\nTIMESTAMP/!s/\n/ /;ta;P;D' file

在patten空间中收集行,用空格替换换行符,然后在遇到下一行TIMESTAMP时打印第一行。

N.B。预计第一行是TIMESTAMP,如果不使用:

sed '/^TIMESTAMP/!b;:a;N;/\nTIMESTAMP/!s/\n/ /;ta;P;D' file