Unix 将固定长度的文件转换为csv文件

Unix 将固定长度的文件转换为csv文件,unix,csv,awk,sed,Unix,Csv,Awk,Sed,我怎样才能: 将固定长度的文件转换为csv文件 根据列长度从输入文件(固定长度文件)拆分记录 我尝试使用'awk'转换文件,但是由于记录中有空格,结果不正确 输入文件: 4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640 00409164 4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640 00409164 4002000W1ABCDABCD7821 12345

我怎样才能:

  • 将固定长度的文件转换为csv文件

  • 根据列长度从输入文件(固定长度文件)拆分记录

  • 我尝试使用'awk'转换文件,但是由于记录中有空格,结果不正确

    输入文件:

    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    004009164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    004009164
    
    ABC_ID,     def_sc, sde_hd,   mln_hfg,        ghi_jkl,     ijk_klm,  pqr_xyz
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    
    第一条记录从4002000w1abcd7821开始,在 00409164

    共有6条记录

    输入文件包含表的6条记录

    记录中有40多列,我只提到了其中的几列

    列的固定长度如下所示:

    ABC_ID(9), def_sc(8), sde_hd(8),mln_hfg(12), ghi_jkl(13),ijk_klm(6),pqr_xyz(10)
    
    预期产出如下:

    ABC_ID(9), def_sc(8), sde_hd(8),mln_hfg(12), ghi_jkl(13),ijk_klm(6),pqr_xyz(10)
    
    输出文件:

    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    00409164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    004009164
    4002000W1ABCDABCD7821 12345671LSN12301630 00000000000091640
    004009164
    
    ABC_ID,     def_sc, sde_hd,   mln_hfg,        ghi_jkl,     ijk_klm,  pqr_xyz
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    4002000W1, ABCDABCD,78211234, 56702291LSN1, 2301630000000, 000916, 4000409164
    
    这是否可以使用sed命令实现


    请提出建议。

    您想要什么还不完全清楚,但GNU awk用于字段宽度和多字符RS是一种选择:

    $ awk -v RS='^$' -v FIELDWIDTHS="9 8 8 8" -v OFS=', ' '{gsub(/\n/,""); print $1, $2, $3, $4}' file
    4002000W1, ABCDABCD, 78211234, 56789071
    

    下面是一个Perl解决方案:

    use strict;
    use warnings;
    
    my @fmt = (9, 8, 8, 12, 13, 6, 10);
    my @head = qw(ABC_ID def_sc sde_hd mln_hfg ghi_jkl ijk_klm pqr_xyz);
    
    my $rec_len = do { my $sum; for(@fmt) { $sum += $_ }; $sum };
    
    my $fn = 'file';
    open(my $fh, '<', $fn) or die "Could not open file '$fn': $!\n";
    my $str = do {local $/ = undef; <$fh>};
    close($fh);
    $str =~ s/\s*//g;
    my $regex = join ("", map { "(.{$_})" } @fmt);
    
    my $head_fmt = join (", ", map { "%-". $_ . "s", } @fmt) . "\n";
    printf $head_fmt, @head;
    
    while ( $str =~ /(.{$rec_len})/g ) {
        my @f = $1 =~ /$regex/;
        print join(", ", @f) . "\n";
    }
    
    输入文件: 输出文件: 要添加第一行,请首先在
    BEGIN{…}
    中打印它:

    awk -v FIELDWIDTHS="9 8 8 12 13 6 10" 'BEGIN{print "ABC_ID,    def_sc,   sde_hd,   mln_hfg,        ghi_jkl,     ijk_klm,  pqr_xyz"} NR%2{temp=$0;next;} {$0=temp$0; gsub(/ /,""); print $1,$2,$3,$4,$5,$6,$7}' OFS=','  file
    
    说明:
    • FIELDWIDTHS=“9 8 12 13 6 10”
      指定要打印的字段长度
    • NR%2{temp=$0;next;}
      temp
      变量中存储奇数行(将用于连接这对行)
    • $0=temp$0
      连接每个连续行<代码>$0是当前行,
      temp
      是当前行之前的行
    • gsub(//,“”)删除空格字符
    • print$1、$2、$3、$4、$5、$6、$7
      FIELDWIDTHS

    请像我在输出文件上做的那样,使用代码标签编辑输入文件数据。删除输入文件中的所有
    。“56789071……”在哪个字符处停止?。您需要4列或6列来显示这6条记录?感谢您的回复。但是当我在输入文件上使用上述命令时,我得到的输出是:4002000W1ABCD782112345678071001080600W1VUF342116002902291LSN123016030000000000400000000000009164000400000091645012500000000。没有按照指定的长度对记录进行分隔,而是将空格替换为“,”。这实际上不是预期的结果。@user229691您使用的是哪个版本的
    awk
    ?@user229691我想您必须安装
    gawk
    才能使用
    FIELDWIDTHS
    谢谢@HåkonHægland,安装“gawk”很有效,但是,它从输入文件中读取一条记录。其余的记录没有被读取。感谢@Hakon脚本,但我需要在shell或gawk中完成。
    awk -v FIELDWIDTHS="9 8 8 12 13 6 10" 'BEGIN{print "ABC_ID,    def_sc,   sde_hd,   mln_hfg,        ghi_jkl,     ijk_klm,  pqr_xyz"} NR%2{temp=$0;next;} {$0=temp$0; gsub(/ /,""); print $1,$2,$3,$4,$5,$6,$7}' OFS=','  file