如何根据第一个字段是否为空来加入相邻行?

时间:2014-04-01 03:16:44

标签: sed awk text-parsing reformat

我可以根据前几个字符是否为空白在前一行中添加一行吗?

例如,我有以下数据:

zone:  z_ABCSVR01_STORAGE1
                ABCSVR; STORAGE1_P1;
        STORAGE_P2  
zone:  z_SUNSVR1_NBUSANCP
                SUNSVR1; NBUSANCP;
zone:  z_WINSVR01_STORAGE2
                WINSVR01; STORAGE1_P2;
        STORAGE_P3

我需要以下输出:

z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1;    STORAGE_P2                      
z_SUNSVR1_NBUSANCP  SUNSVR1; NBUSANCP;               
z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2;  STORAGE_P3     

5 个答案:

答案 0 :(得分:4)

如果你有GNU awk

,这是另一种方法
$ awk -v RS='zone:' '$1=$1' file
z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1; STORAGE_P2
z_SUNSVR1_NBUSANCP SUNSVR1; NBUSANCP;
z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2; STORAGE_P3

答案 1 :(得分:2)

使用awk

awk '{printf (/^zone/)?RS $0:FS $0}' file

zone:  z_ABCSVR01_STORAGE1                 ABCSVR; STORAGE1_P1;         STORAGE_P2
zone:  z_SUNSVR1_NBUSANCP                 SUNSVR1; NBUSANCP;
zone:  z_WINSVR01_STORAGE2                 WINSVR01; STORAGE1_P2;         STORAGE_P3

awk '{printf (/^[[:space:]]/)?FS $0:RS $0}' file

如果你需要删除无用的空格:

awk '{printf (/^zone/)?RS $0:FS $0}' file|awk '$1=$1'

zone: z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1; STORAGE_P2
zone: z_SUNSVR1_NBUSANCP SUNSVR1; NBUSANCP;
zone: z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2; STORAGE_P3

答案 2 :(得分:0)

sed -n '1h;1!H;${x;s/\n  *//g;p;}' YourFile

在连接线时也删除空格

答案 3 :(得分:0)

如果GNU awk可用,@ jaypal的简洁优雅解决方案就是您的选择。

这里有一个符合POSIX标准的解决方案,它试图点缀我并跨越t(使得@ jaypal&#39的解决方案不合规的原因是使用包含多个(文字)字符的RS(记录分隔符)值:

  • 根据OP
  • 的请求,它会从输出中删除zone:
  • 它不会在开头打印额外的\n或省略尾随的。{/ li>
  • 它使用格式参数安全地使用printf,以避免意外控制char。输入线的扩展。
awk '{ 
      if ($1=="zone:") { sep=(notFirst++ ? ORS : ""); $1=""; $0=substr($0,2) } 
      else             { sep=OFS; $1=$1; }
      printf "%s%s", sep, $0
     }    
    END { print }
    ' file

这是同一个程序的评论很多的版本,希望能够解释这里使用的awk更加神秘的功能:

awk '
  { 
    if ($1=="zone:") { # Zone lines            
        # Determine the separator to *precede* the output line:
        # ORS, the output *record* separator, which defaults to \n
        # - unless it is the very first line.
        # Net effect: zone lines start new output lines.
      sep=(notFirst++ ? ORS : ""); 
        # Remove the `zone:` field by setting the first field,
        # $1, to an empty string.
        # Note: This causes the entire line to be rebuilt by joining the
        #       fields with OFS, the output field separator, which defaults
        #       to a space. Multiple adjacent space chars. are folded into 
        #       one in the process.
      $1=""; 
        # Remove the space char. at the beginning of the rebuilt
        # line that stems from setting $1 to an empty string.
      $0=substr($0,2)
    } else {         # Non-zone lines
        # Determine the separator to *precede* the output line:
        # just the regular output *field* separator (space), 
        # effectively causing this line to be appended to the
        # previous one.
      sep=OFS;
        # Trigger rebuilding the line so as to fold 
        # multiple adjacent space chars. into one.
      $1=$1;
    }    
      # Output the separator followed by the rebuilt line.
    printf "%s%s", sep, $0
  }
    # Since the `printf` statement above never outputs
    # a *terminating* \n, we output one at the very end.
  END { print }
  ' file

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed ':a;$!N;/\nzone:/!s/\n\s*/ /;ta;s/^zone:\s*//;P;D' file