【问题标题】:Perl: read file and re-arrange into columnsPerl:读取文件并重新排列成列
【发布时间】:2015-01-15 12:11:22
【问题描述】:

我有一个要读取的文件,其结构如下:

编辑:我让这个例子更具体一点,以阐明我需要什么

HEADER
MORE HEADER
POINTS 2 
x1 y1 z1
x2 y2 z2
VECTORS velocities
u1 v1 w1
u2 v2 w2
VECTORS displacements
a1 b1 c1
a2 b2 c2

包含某些数据的块的数量是任意的,它们的顺序也是任意的。
我只想读取“点”和“向量位移”下的数据,并按以下格式重新排列它们:

x1 y1 z1 a1 b1 c1
x2 y2 z2 a2 b2 c2

我设法将 xyz 和 abc 块读入单独的数组,但我的问题是将它们组合成一个。

我应该提到我是一个 perl 新手。有人可以帮帮我吗?

【问题讨论】:

    标签: perl file-io


    【解决方案1】:

    使用 范围操作符 使这变得非常简单。表达式

    /DATA-TO-READ/ .. /DATA-NOT-TO-READ/
    

    在范围的第一行(DATA-TO-READ 行)计算为 1,在第二行计算为 2,以此类推。在最后一行(DATA-NOT-TO-READ 行)E0 被附加到计数中,以便计算到相同的数值,但也可以测试为最后一行。在超出范围的行上,它的值为 false

    这个程序在数组@output 中累积数据,并在输入结束时打印它。它期望输入文件的路径作为命令行参数。

    use strict;
    use warnings;
    
    my (@output, $i);
    
    while (<>) {
      my $index = /DATA-TO-READ/ .. /DATA-NOT-TO-READ/;
      if ($index and $index > 1 and $index !~ /E/) {
        push @{ $output[$index-2] }, split;
      }
    }
    
    print "@$_\n" for @output;
    

    输出

    x1 y1 z1 a1 b1 c1
    x2 y2 z2 a2 b2 c2
    

    【讨论】:

    • 太好了,谢谢。我实际上更喜欢这种方法,因为它将结果存储在一个数组中。如果每个块的标题不同,显然这也有效。我可以在一秒钟内重复该操作,不同的范围
    • @djun:如果你用一个例子来说明这一点,我相信有比 “重复操作” 更简洁的做事方式。请显示您正在谈论的实际数据。
    • 谢谢,我编辑了这个问题,使它现在非常类似于实际的文件格式。
    【解决方案2】:

    我只使用 1 个数组来记住前 3 列。处理第二部分数据时可以直接输出。

    #!/usr/bin/perl
    use strict;
    use warnings;
    
    my @first;                                  # To store the first 3 columns.
    my $reading;                                # Flag: are we reading the data?
    while (<>) {
        next unless $reading or /DATA-TO-READ/; # Skip the header.
    
        $reading = 1, next unless $reading;     # Skip the DATA-TO-READ line, enter the
                                                # reading mode.
        last if /DATA-NOT-TO-READ/;             # End of the first part.
    
        chomp;                                  # Remove a newline.
        push @first, $_;                        # Remember the line.
    }
    
    undef $reading;                             # Restore the flag.
    while (<>) {
        next unless $reading or /DATA-TO-READ/;
    
        $reading = 1, next unless $reading;
        last if /DATA-NOT-TO-READ/;
    
        print shift @first, " $_";              # Print the remembered columns + current line.
    }
    

    【讨论】:

    • 太棒了,完美运行!而且比我尝试过的任何东西都要短一百万倍
    • 如果可能的话,您能否回答我一个关于您的解决方案的问题:阅读第一部分后,您从数组中删除换行符,对吗?那么第二部分怎么可能总是附加在正确的行中呢?或者:shift如何知道一行的结束?
    • @djun:我只从前 3 列中删除换行符。第 6 列之后还有一个换行符,它永远不会进入数组:它是直接打印的。
    • 谢谢,不确定我是否误解了你,但我真正想知道的是:从前 3 列中删除换行符后,添加第二组。它们是如何正确放置的,因为此时第一组中没有更多的换行符来指示第二组所属的位置?对不起,如果我误解了你
    • @djun:我将这些行保存在一个数组中,而不是单个字符串中。
    猜你喜欢
    • 2019-06-20
    • 2015-12-19
    • 1970-01-01
    • 1970-01-01
    • 2015-08-28
    • 2019-05-09
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    相关资源
    最近更新 更多