使用下面行中的值填充缺失的字段

使用下面行中的值填充缺失的字段

我有一个以分号分隔的数据文件,其中只有几行具有“完整”数据集。他们是在最后数据集适用的行块的位置。我想使用 shell 脚本(或类似的命令行工具)将数据从这个完整填充的行添加到上面的行。

例如,假设我的文件包含以下数据:

86540701
86951202
86262402
86509002
86770802
86459902
86301002
86485102
86556002;Vivo Y11;1630000;NULL;;;
86447404
86161405
86388604
86106105
86426405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;

我希望能够找到完整的行并将该数据替换为上面不完整的行,如下所示:

86540701;Vivo Y11;1630000;NULL;;;
86951202;Vivo Y11;1630000;NULL;;;
86262402;Vivo Y11;1630000;NULL;;;
86509002;Vivo Y11;1630000;NULL;;;
86770802;Vivo Y11;1630000;NULL;;;
86459902;Vivo Y11;1630000;NULL;;;
86301002;Vivo Y11;1630000;NULL;;;
86485102;Vivo Y11;1630000;NULL;;;
86556002;Vivo Y11;1630000;NULL;;;
86447404;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86161405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86388604;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86106105;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86426405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;

答案1

这是一个我们可以使用的任务tac以相反的顺序解析文件:

tac file | awk -F';' 'NF > 1 {p = substr($0,index($0,FS))} {print $1 p}' | tac

因此,我们不存储任何行,而是在读取每一行后进行打印。

NF > 1我们存储从行首FS到行尾的子字符串以供将来使用时。

答案2

另一种awk基于 的解决方案使用双通道方法(需要 GNUawknawkgensub()函数):

awk -F';' 'FNR==NR{if (NF>1) data[++i]=gensub(/^[^;]+/,"","1");next}
           {if (NF==1) $0=$0 data[j+1]; else j++;} 1' input.csv input.csv

这将扫描文件两次。第一次,它创建包含多个字段的那些行的“数据部分”数组。第二次,它替换丢失的数据部分,并在每次遇到“完整”行时增加数组计数器,以便下一个数据部分替换后面的行。

答案3

使用sed

sed -E '
    /;/!{ :a N;/;/!{ s/\n/-/;ta; }; };
    /;/ { s/\n/-/; };
    :c s/([^-]*)-([^;]*)(;.*)$/\1\3\n\2\3/; tc' infile

答案4

GNU sed在打开扩展正则表达式模式的情况下使用-E

  • 将记录存储在保留中,并在操作开始时等待分号记录。
  • 当我们遇到分号线时,合并过程开始,其中模式空间的最后部分(=分号线)被附加到模式空间的第一部分,并且第一部分被打印并剥离。这一直持续到我们耗尽模式空间为止。

$ sed -Ee '/\n/ba
    H;/;/!d;z;x;D;:a
    s/\n(.*\n)?[^;]+(;.*)/\2&/
    P;/\n.*\n/D;s/.*\n//
' file

$ perl -lne '$, = ";";
    push(@A,$_),next if !/;/;
    my $a = s/.*?;//r;
    print $_, $a for splice @A;
    print;
' file

相关内容