将空列添加到空列

Add null to the columns which are empty

我正在尝试使用 perlawk 将空列置为空,以查找列数,可以使用 header 的列数。我尝试使用 perl 和一些正则表达式来执行解决方案。但是,输出看起来非常接近所需的输出,但如果仔细观察,第一行显示的数据不正确。

输入数据:

id      name           type          foo-id  zoo-id  loo-id-1  moo-id-2
-----  ---------------  -----------  ------  ------  ------  ------
0      zoo123        soozoo          8               31        32
51     zoo213        soozoo          48      51
52     asz123        soozoo          47      52
53     asw122        soozoo          1003    53
54     fff123        soozoo          68      54
55     sss123        soozoo          75      55
56     ssd123        soozoo          76      56

预期输出:

0      zoo123        soozoo          8       null      31        32
51     zoo213        soozoo          48      51        null      null
52     asz123        soozoo          47      52        null      null
53     asw122        soozoo          1003    53        null      null
54     fff123        soozoo          68      54        null      null
55     sss123        soozoo          75      55        null      null
56     ssd123        soozoo          76      56        null      null

非常接近解决方案,但第 1 行显示的数据不正确:

echo "$x"|grep -E '^[0-9]+'  |perl -ne 'm/^([\d]+)(?:\s+([\w]+))?(?:\s+([-\w]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?(?:\s+([\d]+))?/;printf "%s %s %s %s %s %s %s\n", , //"null", //"null",//"null",//"null",//"null",//"null"' |column -t
0   zoo123  soozoo  8     31  32    null
51  zoo213  soozoo  48    51  null  null
52  asz123  soozoo  47    52  null  null
53  asw122  soozoo  1003  53  null  null
54  fff123  soozoo  68    54  null  null
55  sss123  soozoo  75    55  null  null
56  ssd123  soozoo  76    56  null  null

使用 GNU awk:

awk 'NR>2{                     # ignore first and second row
       NF=7                    # fix number of columns
       for(i=1; i<=NF; i++)    # loop with all columns
         if($i ~ /^ *$/){      # if empty or only spaces
           $i="null"
         }
       print [=10=]}' FIELDWIDTHS='7 14 16 8 8 10 8' OFS='|' file | column -s '|' -t

作为一行:

awk 'NR>2{NF=7; for(i=1;i<=NF;i++) if($i ~ /^ *$/){$i="null"} print [=11=]}' FIELDWIDTHS='7 14 16 8 8 10 8' OFS='|'  file | column -s '|' -t

输出:

0        zoo123          soozoo            8         null  31          32
51       zoo213          soozoo            48        51    null        null
52       asz123          soozoo            47        52    null        null
53       asw122          soozoo            1003      53    null        null
54       fff123          soozoo            68        54    null        null
55       sss123          soozoo            75        55    null        null
56       ssd123          soozoo            76        56    null        null

参见:8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

当您要解析固定宽度的字符串时,您会发现 unpack() 是比正则表达式更好的工具。

这应该演示如何操作。我会把它留给你把它转换成单行。

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';

use Data::Dumper;

while (<DATA>) {
  next if /^\D/; # Skip lines that don't start with a digit

  # I worked out the unpack() template by counting columns.
  my @data = map { /\S/ ? $_ : 'null' } unpack('A7A14A16A8A8A8A8');

  say join ' ', @data;
}

__DATA__
id      name           type          foo-id  zoo-id  loo-id-1  moo-id-2
-----  ---------------  -----------  ------  ------  ------  ------
0      zoo123        soozoo          8               31        32
51     zoo213        soozoo          48      51
52     asz123        soozoo          47      52
53     asw122        soozoo          1003    53
54     fff123        soozoo          68      54
55     sss123        soozoo          75      55
56     ssd123        soozoo          76      56

输出:

$ perl unpack | column -t
0   zoo123  soozoo  8     null  31    32
51  zoo213  soozoo  48    51    null  null
52  asz123  soozoo  47    52    null  null
53  asw122  soozoo  1003  53    null  null
54  fff123  soozoo  68    54    null  null
55  sss123  soozoo  75    55    null  null
56  ssd123  soozoo  76    56    null  null