【问题标题】:Extracting continuous values and print all the lines提取连续值并打印所有行
【发布时间】:2012-03-02 11:06:43
【问题描述】:

如果值连续超过 4 行(如果 col1 中的值相同),我想提取行,但应该打印所有行(应该打印超过 4 行)。

如果 col1 中的值相等,并且 col2 和 col3 中的值连续(如连续数字)超过接下来的 4 行,则返回这些行。行 col3 中的值可以相等,也可以小于下一行 col2 值的 100。

这里连续并不意味着 1 行(即 1 行 col3 - col2)。这意味着与下一行的 col2 值相比,行的 col3 值。

我的文件是 ->

一个 0 100 A1 0 100 A1 100 200 A1 200 300 A1 400 500 A1 500 600 A1 600 700 A1 700 800 A1 1600 1700 A2 100 200 A2 200 300 A2 400 500 A2 500 600 A2 600 700 A3 800 900

想要的输出是->

A1 0 100 A1 100 200 A1 200 300 A1 400 500 A1 500 600 A1 600 700 A1 700 800 A2 100 200 A2 200 300 A2 400 500 A2 500 600 A2 600 700

这里还有 1 个示例 -> 我的输入文件->

一个 0 100 A1 0 100 A1 100 200 A1 200 300 A1 500 600 A1 600 700 A1 700 800 A1 1600 1700 A2 100 200 A2 200 300 A2 400 500 A3 800 900

输出->

“没有连续的行”。

现在没有输出,因为应该有超过 4 行具有相同的 col1 值,并且这些行的 col3 值应该等于或小于 100,与下一行相比。

到目前为止,我尝试了这个但没有用 ->

use strict;
use warnings;

*ARGV or die "No input file specified";
open *first, '<',$ARGV[0] or die "Unable to open input file: $!";
my @data;
while (<first>) {

     if (not @data) {
     @data = split;
     next;
     }

     my @new = split /\s+/;

     if ($new[0] eq $data[0] and $new[1] <= $data[2]+ 100) {
     $data[2] = $new[2];
          if ( $data[2] - $data[1] >= 500){
             print join("\t", @new), "\n";
          }
     }

    else {
    @data = @new;
    }
}

请帮忙。

【问题讨论】:

  • "col2 和 col3 中的值是连续的(就像一个连续的数字)",连续是什么意思?我不知道什么是连续数。
  • @Qtax :考虑 1 行(行),其 col3 为 100。然后我们必须查看下一行(行)的 col2 是否也是 100(或最多 200) .如果这种情况连续发生 5 行,则打印这 5 行。
  • M42 的答案应该适合你。

标签: perl


【解决方案1】:

怎么样:

#!/usr/bin/perl 
use strict;
use warnings;
use Data::Dump qw(dump);
use 5.010;

$_ = <DATA>;
chomp;
my ($p_key, $p_col1, $p_col2) = split;
my @result = ($_);
open my $fh, '>', 'path/to/output_file' or die "unable to open file:$!";
while(<DATA>) {
    chomp;
    my ($key, $col1, $col2) = split;
    if ($key eq $p_key) {
        if ($col1 <= $p_col2+100) {
            push @result, $_;
        } else {
            print_to_file($fh, \@result) if (@result > 3);
            @result = ();
        }
    } else {
        print_to_file($fh, \@result) if (@result > 3);
        @result = ($_);
    }
    ($p_key, $p_col2) = ($key, $col2);
}
print_to_file($fh, \@result) if (@result > 3);

sub print_to_file {
    my $fh = shift;
    my $res = shift;
    while(@$res) {
        print $fh, $_, "\n";
    }
}
__DATA__
A   0    100
A1  0    100
A1  100  200
A1  200  300
A1  400  500
A1  500  600
A1  600  700
A1  700  800
A1  1600 1700
A2  100  200
A2  200  300
A2  400  500
A2  500  600
A2  600  700
A3  800  900

输出:

(
  "A1  0    100",
  "A1  100  200",
  "A1  200  300",
  "A1  400  500",
  "A1  500  600",
  "A1  600  700",
  "A1  700  800",
)
(
  "A2  100  200",
  "A2  200  300",
  "A2  400  500",
  "A2  500  600",
  "A2  600  700",
)

【讨论】:

  • 我猜 OP 也想检查 $col1 &gt;= $p_col2,可能还有 $col1 &gt;= $col2
  • @Qtax:我不确定他真正想要什么。但是根据给出的例子,如果 $col1 不大于 $p_col2+100,他想保留一行。即A1 200 300A1 400 500 但不是A1 700 800/ A1 1600 1700
  • @M42:谢谢。我尝试了您的代码及其工作,但有时它没有给出最后一行。此输出也出现在屏幕上,我无法将其存储在文件中。有没有办法将输出存储在文件中(制表符分隔),并且应该与我们的输入文件采用相同的格式。 (没有引号,没有括号,也没有逗号)。
  • @Vikas:要存储在文件中,只需将所有dump@result 替换为在输出文件中打印的循环即可。你能举一个没有打印最后一行的例子吗?
  • @M42:对不起,那是我的错误。它正在打印最后一行。所以如果我将所有的dump@result都替换掉,那么就意味着,Data::Dump就没有用了吗?
猜你喜欢
  • 2020-06-24
  • 1970-01-01
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2018-08-30
  • 1970-01-01
  • 2023-03-03
相关资源
最近更新 更多