我有一个包含时间戳的行数的文件,中间有几行。例如,
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}'
但它只会更改模式的每个替代事件。跟踪消息中不需要任何模式。在这种情况下,我更倾向于使用sed
或awk
。
答案 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