如何在确切的位置合并两条线,就像使用awk或sed上拉/下拉一样

时间:2016-07-01 16:19:29

标签: awk sed gawk

我的文件的示例输出在这里给出

! S R Number  :            Class :       ! 
                635035               3     
! Name        :                          ! 
                ADAM BASHA               
+========================================+ 
! Code  ! Description     !       Amount ! 
+========================================+ 
! 2222  ! Tech.Exam Allow !       340.00 ! 
! 3104  ! D A             !    19,524.43 ! 
! 3107  ! H R A           !     3,984.40 ! 
! 4113  ! Transport Allow !       460.00 ! 
!                         :              ! 
  Net Amount Payable  :        24,308.83
! S R Number  :            Class :       ! 
                551820               2     
! Name        :                          ! 
                TOM SMITH              
+========================================+ 
! Code  ! Description     !       Amount ! 
+========================================+ 
! 3104  ! D A             !    19,404.41 ! 
! 3107  ! H R A           !     3,960.60 ! 
! 4113  ! Transport Allow !       460.00 ! 
!                         :              ! 
  Net Amount Payable  :        23,825.01   
! S R Number  :            Class :       ! 
                550044               3     
! Name        :                          ! 
                ROBERT LOUIS           

我想要将与下面给出的这种格式类似的每两行合并为

 ! S R Number  :            Class :       ! 
                635035               3

我想要将两行合并如下

! S R Number  : 635035     Class :   3   !

整个结果应如下:

! S R Number  : 635035     Class :   3   ! 
! Name        : ADAM BASHA               ! 
+========================================+ 
! Code  ! Description     !       Amount ! 
+========================================+ 
! 2222  ! Tech.Exam Allow !       340.00 ! 
! 3104  ! D A             !    19,524.43 ! 
! 3107  ! H R A           !     3,984.40 ! 
! 4113  ! Transport Allow !       460.00 ! 
! Net Amount Payable  :        24,308.83 !
! S R Number  : 551820     Class :   2   ! 
! Name        : TOM SMITH                !
+========================================+ 
! Code  ! Description     !       Amount ! 
+========================================+ 
! 3104  ! D A             !    19,404.41 ! 
! 3107  ! H R A           !     3,960.60 ! 
! 4113  ! Transport Allow !       460.00 ! 
! Net Amount Payable  :        23,825.01 !
! S R Number  : 550044     Class :   3   ! 
! Name        : ROBERT LOUIS             !

文件太大,所以我发布了一个样本。此输出文件似乎将某些行拆分为两行,如包含S R Number, Name and Net Amount Payable的行。请提供解决方案。

已经给出的答案工作正常,唯一的事情是它们处理所有行而不是仅处理分割的行。谢谢大家。

我使用实际例子编辑了我的问题。

4 个答案:

答案 0 :(得分:3)

$ cat tst.awk
/^[^[:space:]]/ {
    if (NR>1) { print buf }
    buf = $0
    next
}
{
    if (/:/) { sub(/:/," ",buf) }
    while ( match($0,/[^[:space:]]+/) ) {
        buf = substr(buf,1,RSTART-1) substr($0,RSTART,RLENGTH) substr(buf,RSTART+RLENGTH)
        $0 = sprintf("%*s",RSTART+RLENGTH-1,"") substr($0,RSTART+RLENGTH)
    }
}
END { print buf }

$ awk -f tst.awk file
! S R Number  : 635035     Class :   3   !
! Name        : ADAM BASHA               !
+========================================+
! Code  ! Description     !       Amount !
+========================================+
! 2222  ! Tech.Exam Allow !       340.00 !
! 3104  ! D A             !    19,524.43 !
! 3107  ! H R A           !     3,984.40 !
! 4113  ! Transport Allow !       460.00 !
! Net Amount Payable  :        24,308.83 !
! S R Number  : 551820     Class :   2   !
! Name        : TOM SMITH                !
+========================================+
! Code  ! Description     !       Amount !
+========================================+
! 3104  ! D A             !    19,404.41 !
! 3107  ! H R A           !     3,960.60 !
! 4113  ! Transport Allow !       460.00 !
! Net Amount Payable  :        23,825.01 !
! S R Number  : 550044     Class :   3   !
! Name        : ROBERT LOUIS             !

答案 1 :(得分:1)

使用一个字符长度字段的另一个gawk解决方案

$ awk 'BEGIN{OFS=FS=""} 
            {if(NR%2) split($0,p);
             else {for(i=1;i<=NF;i++) if($i==" ") $i=p[i]; 
                   print}}' file

Name : Adam Basha                     Class :3

这里假设第二条记录长于第一条记录(如果没有将循环结束条件更改为最大长度(p)和NF或之后附加额外记录。

答案 2 :(得分:0)

这个(不是很优雅)命令应该为输入文件test执行工作:

awk 'BEGIN{odd=1}
     odd{line=$0;odd=0;next}
     {odd=1;nline=""
      for(i=1; i<=length($0);i++){
          nline=substr($0,i,1)==" " && i <= length(line)? nline""substr(line,i,1) : nline""substr($0,i,1)
      }
     print nline
     }' test

输出:

Name : Adam Basha                     Class : 3

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed -r 'N;/\n\s/!{P;D};s/^/\n/;ta;:a;/\n.*\n$/s/\n//g;t;s/\n\n/\n \n/;s/\n(\S)(.*)\n./\1\n\2\n/;ta;s/\n.(.*)\n(.)/\2\n\1\n/;ta' file

该过程组合了所需的线条并使用从左向右移动的唯一标记(换行符),比较标记后面的单个字符。如果第一个不是空格,请保留它并将标记推到它上面。否则,将第一个替换为第二个并将标记推进其上。如果标记已到达行尾,则在第一行引入额外空格时除去第一行短于第二行的标记。