如何用sed或awk将以数字开头的记录多行合并为单行?
需求与解决方案
问题描述
需要处理文本文件,仅将以数字开头的记录行及其后续所有关联行(直到下一个数字开头的记录出现)合并为单行,其余非记录行保持原样。
示例输入文本
max system cycles: 9087AED max system scans: 900 Secure connection date:.... 1: ID = XX_34_4_7_6e field1 = trc_1_1 field2 = 24 Blank field2 = field3 XX = OK (45) field4 XX = assfsdf field5 XX YY = sdffee (ssddT) field6 a b c d = no field7 ID = zip field8 = city 2: ID = YY_z3_4_t20 field1 = xyz1_1_t field2 = 20 Blank field2 = field3 XX = OK (5)
之前尝试的问题
- 执行
sed -e '/[0-9]/ N; s/\n/,/' /var/tmp/tmp1:仅能追加一行关联内容,且错误合并非记录行。 - 执行
sed '/./{H;$!d} ; x ; s/.\n/,/g; s/ *//g' /var/tmp/tmp1:会合并所有行,不符合仅处理数字记录的需求。
解决方案
方案1:使用Awk脚本(逻辑清晰易维护)
awk ' /^[0-9]+:/ { if (line != "") print line line = $0 next } /^[[:space:]]+/ { sub(/^[[:space:]]+/, "", $0) line = line ", " $0 next } { if (line != "") { print line line = "" } print $0 } END { if (line != "") print line } ' /var/tmp/tmp1
逻辑说明:
- 匹配数字开头的记录行:若之前有缓存的合并行则先打印,再将当前行作为新合并行的起始。
- 匹配空格开头的关联行:移除开头所有空格后,追加到当前合并行末尾(用
,分隔)。 - 匹配其他非记录行:若有缓存的合并行先打印,再直接输出当前行,清空缓存。
- 脚本结束时,若还有未打印的合并行则输出。
方案2:使用Sed脚本(纯文本流处理)
sed -n ' /^[0-9]/ { H :loop n /^[0-9]/! { s/^[[:space:]]*// H b loop } x s/\n/, /g p H b loop } /^[^0-9]/p ' /var/tmp/tmp1
逻辑说明:
- 仅处理数字开头的行:先将该行存入保持空间。
- 进入循环读取下一行:若不是数字开头,移除空格后存入保持空间,继续循环。
- 遇到下一个数字开头的行:交换保持空间与模式空间,将所有换行替换为
,后打印,再将当前数字行存入保持空间,继续循环。 - 非数字开头的行直接打印。
内容的提问来源于stack exchange,提问作者Rajeev
相关产品推荐
相关产品推荐

