perl 在文件中匹配模式后,分析行并保存到不同的数组

w8rqjzmb  于 2023-10-24  发布在  Perl
关注(0)|答案(2)|浏览(121)

示例文件:

some texts....
....

FINAL RESULTS

....
some texts

Needed data:   -25.684   -61.647   -20.061            #need this line
               -61.647    82.482   -15.683            #need this line
               -20.061   -15.683   -56.799            #DOES NOT need this line
Needed data:   -24.557   -48.468     2.592            #need this line
               -48.468    62.053    -6.742            #need this line
               -2.592    -6.742   -37.495             #DOES NOT need this line
Needed data:   -42.875  -101.901   -30.377            #need this line
               -101.901   134.323   -24.259           #need this line
               -30.377   -24.259   -91.448            #DOES NOT need this line

我想搜索“最终结果”,然后搜索“需要的数据”,并提取第一和第二行,但不是第三行的数字,并把它们放入数组。
以下是我到目前为止所做的:

my $in_sec;
    open(IN, "< t.in") or die;
    while (<IN>)
    {
      if    (/FINAL RESULTS/)     { $in_sec = 1; }
      elsif (/(?<!FINAL RESULTS):/) { $in_sec = 0; }

      if ($in_sec) {
        if(/Needed data/) {
         @a = split;
         print "@a\n";
         if ($_ = <IN>) {
            @b = split;
            print "@b\n";
         }
      }
     }
    }

但什么都没印出来。

dhxwm5r4

dhxwm5r41#

使用Perl的一行程序:

perl -0nE '
    push @a, split for /(?<=Needed data:)\s+\S+\s+\S+\s+\S+\N\s*\S+\s+\S+\s+\S+/g;
    END{say join "\n", @a}
' t.in

作为脚本:

#!/usr/bin/env perl

use strict; use warnings;
use feature 'say';
use File::Slurp;

my @a;
$_ = read_file($ARGV[0]);
push @a, split for /(?<=Needed data:)\s+\S+\s+\S+\s+\S+\N\s*\S+\s+\S+\s+\S+/g;
say join "\n", @a;

输出

-25.684
-61.647
-20.061
-61.647
82.482
-15.683
-24.557
-48.468
2.592
-48.468
62.053
-6.742
-42.875
-101.901
-30.377
-101.901
134.323
-24.259

正则表达式匹配如下:

| 节点|解释|
| --|--|
| (?<=|回头看看有没有:|
| Needed| data:'需要的数据:'|
| )|回溯结束|
| \s+|空格(\n、\r、\t、\f和““)(1次或多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|
| \s+|空格(\n、\r、\t、\f和““)(1次或多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|
| \s+|空格(\n、\r、\t、\f和““)(1次或多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|
| \N|新线|
| \s*|空格(\n、\r、\t、\f和““)(0次或更多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|
| \s+|空格(\n、\r、\t、\f和““)(1次或多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|
| \s+|空格(\n、\r、\t、\f和““)(1次或多次(匹配可能的最大数量))|
| \S+|非空格(除\n、\r、\t、\f和““之外的所有空格)(1次或多次(匹配最大可能量))|

eh57zj3b

eh57zj3b2#

您的elsif测试与Needed data:行中的:匹配。
如果没有该测试,您的代码将产生输出。
下面是一个使用../...的方法:

perl -nE '
    next if 1 .. /FINAL RESULTS/;

    if ( $n = /Needed data/ ... $. ) {
        s/#.*//;
        push @{ $n==1 ? \@a : \@b }, /-?\d+\.\d+/g;
    }

    END {
        say "\@a = @a";
        say "\@b = @b";
    }
' t.in
  • 使用..操作符跳到相关行
  • 处理“需要的数据”和下一行
  • ...类似于..,但延迟了第二次测试
  • $.仅用作始终为正的变量
  • 带注解
  • 提取所有看起来像数字的东西
  • push到适当的阵列
  • 显示存储的数组

相关问题