如何使用awk或sed将两条线合并到一个准确的位置,就像它被上拉/下拉一样

如何使用awk或sed将两条线合并到一个准确的位置,就像它被上拉/下拉一样,awk,sed,gawk,Awk,Sed,Gawk,这里给出了我的文件的输出示例 ! S R Number : Class : ! 635035 3 ! Name : ! ADAM BASHA +========================================+ ! Code ! Descrip

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

! 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             !
这个文件太大了,所以我贴了一个样本。此输出文件似乎将一些行拆分为两行,例如包含编号、名称和应付净额的行。请提供一个解决方案

已经给出的答案很好,唯一的问题是它们处理所有的行,而不是只处理分割的行。谢谢大家

我已经用一个实际的例子编辑了我的问题。

这个(不是很优雅的)命令应该可以完成输入文件
测试的工作:

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
这个(不是很优雅的)命令应该对输入文件
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


另一个
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
$awk'开始{OFS=FS=”“}
{如果(NR%2)分割($0,p);

else{for(i=1;i另一个
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
$awk'开始{OFS=FS=”“}
{如果(NR%2)分割($0,p);
else{for(i=1;i这可能适合您(GNU-sed):

该过程结合了所需的行,并使用了唯一的标记(换行符)从左向右移动,比较标记后面的单个字符。如果第一行不是空格,则保留它并将标记前进到其上方。否则,将第一行替换为第二行,并将标记前进到其上方。如果标记已到达行尾,则移除标记,但第一行短于第二行的情况除外在第一行引入了可选空间。

这可能适合您(GNU-sed):


该过程结合了所需的行,并使用了唯一的标记(换行符)从左向右移动,比较标记后面的单个字符。如果第一行不是空格,则保留它并将标记前进到其上方。否则,将第一行替换为第二行,并将标记前进到其上方。如果标记已到达行尾,则移除标记,但第一行短于第二行的情况除外第一行引入了可选空格。

缩进背后的原因是什么?更好?缩进的目的是
条件{action}
块在动作处对齐,相同级别的语句在相同级别缩进。如果它在行中流动并且很短(如
If(x))y
保持一致。我没有漂亮的打印机,有时会出错……我希望这能有所帮助。顺便说一句,我也没有漂亮的打印机。我是漂亮的打印机;)太多的花括号符合我的口味,
awk--profile
会给你更好的代码,如果你愿意的话,但是我喜欢更密集的一行样式。不,不,不。这不是喜欢与否。这是关于坚如磐石的、可读的和可维护的代码。虽然我同意对于一行习惯用法来说规则有点不同,但上面的代码显然不是一行习惯用法和你的缩进风格使它难以阅读、获取和维护。你从不放置内联注释的事实可能是你缩进“风格”的另一个结果。缩进背后的原因是什么?更好?缩进的目的是
条件{action}
块在动作中对齐,相同级别的语句在相同级别的缩进中。如果它在一行中流动并且很短(比如
If(x)y
保持在同一行。我没有漂亮的打印机,有时会出错……我希望这会有所帮助。顺便说一句,我也没有漂亮的打印机。我是漂亮的打印机;)太多的花括号符合我的口味,
awk--profile
会给你更好的代码,如果你愿意的话,但是我喜欢更密集的一行样式。不,不,不。这不是喜欢与否。这是关于坚如磐石的、可读的和可维护的代码。虽然我同意对于一行习惯用法来说规则有点不同,但上面的代码显然不是一行习惯用法和你的缩进风格使它很难阅读、获取和维护。你从不放置内联注释的事实可能是你缩进“风格”的另一个结果。
odd
可以写成
NR%2
odd
可以写成
NR%2
你不应该做的事情更多:-).awk用于操作text.period.full stop。如果您想执行其他操作(移动文件?终止进程?),则应使用其他操作(例如shell)。提供的所有解决方案都很好,但文件中的所有行都在处理中。我只需要合并两行,一行有名称,另一行有实际名称,如问题所述。我在文件中有很多这样的情况。我需要合并具有上述两种模式的两行。谢谢大家解决方案。@EdMorton,我已经编辑了我的问题,并在我的要求中提供了更具代表性的示例输入/输出。非常好的解决方案,先生。非常感谢@Edmortony您的欢迎。如果/当您准备接受解决方案时,请记住单击它旁边的复选标记。请参阅。这是您不应该做的更多事情:-).awk用于操作text.period.full stop。如果您想执行其他操作(移动文件?终止进程?),则应使用其他操作(例如shell)。提供的所有解决方案都很好,但文件中的所有行都在处理中。我只需要合并两行,一行有名称,另一行有实际名称,如问题所述。我在文件中有很多这样的情况。我需要合并具有上述两种模式的两行。谢谢大家解决方案。@EdMorton,我已经编辑了我的问题,并在我的要求中提供了更具代表性的示例输入/输出。非常好的解决方案,先生。
$ 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
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