Shell脚本用于合并由空行分隔的行

时间:2012-12-24 11:27:21

标签: shell sed awk

我有一个巨大的文本文件(500K行),其中一些行分为多行。我试图用分割线来获取记录,显示在一行中。当线被分割时,在下一行的开头之前有一个空行。现在,我循环遍历每一行,在开始时测试字符串(AAAA|)以确定它是否是新行,然后与next连接。但这似乎需要花费很多时间,并想知道是否有更好的方法来做到这一点。此外,一些行分为多行,每个新记录以" AAAA |"开头。

输入文件:

AAAA|XXXX|YYYY|ZZZZ|532920-1*TYCO ELECTRONICS AMP#HDR4-2B-320-PSH2-A*CECO COMPONENT EQUIPMENT CO INC#
AAAA|XXXX|2342342|ADFADFS|A80386DX-33*INTEL CORP#
AAAA|SDFASF|234232322|saddfwq|ER412D-5A*TELEDYNE COMPONENTS#M39016/15-088L*QPL-39016#JMACD-5XL*HI-G INC#914S72101-10L*DRI RELAYS INC#M39016/15-082L*QPL-39016#3SBS1412A2*TYCO ELECTRONICS
CORP#

AAAA|XXXXXXX|5675423|XVASD|N74F132D-T*NXP SEMICONDUCTORS#74F132SC*FAIRCHILD SEMICONDUCTOR CORP#N74F132D*NXP SEMICONDUCTORS#MC74F132D*FREESCALE SEMICONDUCTOR INC#N74F132D,602*NXP SEMICONDU
CTORS#

AAAA|SDFASFSAS|23422|DFGAQWEWE|3SBS1411A2*TYCO ELECTRONICS CORP#914S70301-10L*DRI RELAYS INC#M39016/15-081L*QPL-39016#ER412D-26A*TELEDYNE COMPONENTS#JMACD-26XL*HI-G INC#M39016/15-087L*QPL
-39016#

AAAA|SFRQ3|34543534|NSGBSSDF|3SBS1223A2*TYCO ELECTRONICS CORP#914S60301-10L*DRI RELAYS INC#M39016/15-039L*QPL-39016#914S60301-09L*DRI RELAYS INC#M39016/15-051L*QPL-39016#ER412D-18A/S*TE
LEDYNE COMPONENTS#JMAPD-18XL*HI-G INC#

AAAA|ALSKFJ|1SFAE|ASLKFJSLKSAD|11163-164J*PHILIPS COMPONENTS#SEE_DRAWING_11163-164J*ROHM CO LTD#CF1/4L_164J*KOA SPEER ELECTRONICS INC#SEE_DRAWING_11163-164J*PHILIPS COMPONENTS#CF1/4L
U164J*KOA SPEER ELECTRONICS INC#CF1/4-160K-5%*KOA SPEER ELECTRONICS INC#11163-164J*ROHM CO LTD#131-00164-0053*HONEYWELL CROSS REFERENCE#CF1/4CT52A164J*KOA SPEER ELECTRONICS INC#CF1/4CT52R164J*KOA SPEE
R ELECTRONICS INC#||

AAAA|ASDFAA|1ASFSDAS|ASDFSA|MF 55 D 4323 F*KOA SPEER ELECTRONICS INC#2322156X4324*BC COMPONENTS INC#MF1/4DLT52R4323F*KOA SPEER ELECTRONICS INC#2322 156 X 4324*BC COMPONENTS INC#SFR55432K0
1%*BC COMPONENTS INC#CCF-55 4323 F*VISHAY DALE#CCF-554323F*VISHAY DALE#MF1/4DL_4323F*KOA SPEER ELECTRONICS INC#RN55D4323F*MILITARY SPECIFICATIONS#SFR55 432K0 1%*BC COMPONENTS INC#MF55D4323F*KOA SPEER
ELECTRONICS INC#||

7 个答案:

答案 0 :(得分:3)

使用Perl保留空行:

perl -ne 'if (!/^$/) { chomp } else { print "\n" } print' input

使用Perl在连接后删除黑线:

perl -ne 'if (!/^$/) { chomp } print' input

使用GNU Sed(不处理posix模式中的最后一行):

sed '/^AAAA/{:l N;/\n./{s/\n//;bl}}' input

答案 1 :(得分:2)

假设只将最后一列拆分为多行:

awk -F"|" 'NF>1{if(x)print x;x=""}{x=x $0;}END{print x}' file

答案 2 :(得分:1)

算法的sed版本“如果某行不以AAAA|开头,只需与上一行连接:”:

sed -n '1x;2,${/^AAAA|/{x;s/\n//g;p};/^AAAA|/!H};${x;s/\n//g;p}' your_file.txt

与所有sed脚本一样,需要一些解释:

  • -n:不要在脚本末尾打印模式空间。
  • 1x:记住保留空间中的第一行(交换保留和模式空间)。
  • `2,$ {...}:为第2行到最后一行。
  • /^AAAA|/{x;s/\n//g;p}:如果该行以新记录模式开头,则在保留空间中保存新行并返回保留空间的前一行(交换保留和模式空间),从前一行中删除新行记录并打印出来。
  • /^AAAA|/!H:如果该行不以新记录模式开头,请将其附加到保留空间中的上一行。
  • ${x;s/\n//g;p}:对于最后一行,从保留空间取回数据,删除换行符并打印。

答案 3 :(得分:0)

以下命令是否缓慢?

awk '!NF{print line; line=""}{line=line$0}' infile

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed ':a;$!N;/\nAAAA/{P;D};s/\n//;ta' file

答案 5 :(得分:0)

似乎每条记录以井号结束。如果那是真的,那么:

awk '{printf("%s", $0)} /#$/ {print ""}' filename

答案 6 :(得分:0)

如果某行不以AAAA|开头,只需与上一行连接:

awk 'NR == 1 { previous = $0 }
     NR > 1 && $0 ~  "^AAAA[|]" { print previous; previous = $0 }
     NR > 1 && $0 !~ "^AAAA[|]" { previous = previous $0 }
     END { print previous }' your_file.txt

我们需要将|放在[]之间,因为它是扩展正则表达式的特殊字符。