如何使用 awk 或 sed 在确切位置合并两行,就好像它被拉 up/down

How to merge two lines in the exact place as if it is pulled up/down using awk or sed

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

! 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 的行。请为此提供解决方案。

已经给出的答案工作正常,唯一的问题是他们处理所有的行,而不是只处理被分割的行。感谢大家。

我已经使用实际示例编辑了我的问题。

这个(不是很优雅)命令应该完成输入文件的工作test

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

输出:

Name : Adam Basha                     Class : 3
$ cat tst.awk
/^[^[:space:]]/ {
    if (NR>1) { print buf }
    buf = [=10=]
    next
}
{
    if (/:/) { sub(/:/," ",buf) }
    while ( match([=10=],/[^[:space:]]+/) ) {
        buf = substr(buf,1,RSTART-1) substr([=10=],RSTART,RLENGTH) substr(buf,RSTART+RLENGTH)
        [=10=] = sprintf("%*s",RSTART+RLENGTH-1,"") substr([=10=],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             !

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

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

Name : Adam Basha                     Class :3

此处假设第二条记录比第一条记录长(如果不是,则将循环结束条件更改为最大长度 (p) 和 NF 或之后追加额外内容。

这可能对你有用 (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./\n\n/;ta;s/\n.(.*)\n(.)/\n\n/;ta' file

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