Perl regex:以给定格式匹配和输出的多行:完全修订

时间:2016-02-28 19:24:58

标签: regex perl

如果有人能够理解如何将内容存储在内存中,知道它在哪里,以及如何以有序的方式再次将其删除,那么在Perl中实现结果将会有很长的路要走。(可能还有所有的编程语言)

我不是程序员。

我正在尝试从旧程序中提取数据'输出并将其导入SQL数据库。提取是件事。

我之前的问题在很大程度上是不正确的,因为我在将数据导入表格时发现,因为我没有足够的数据来自旧程序'输出文件。

我想从错误中吸取教训并重新问我之前的问题,希望这次是正确的。

我在提取数据方面做得很差,就像上次一样。它无法获得正确的数据。

我认为这是一个非常复杂的问题,但也许并非如此。 它肯定高于我目前的Perl水平,也许永远都是。

对我错误措辞问题的答案已被部分理解。非常感谢他们。

如果我可以总结一下,我的主要任务就是处理问题的类型:'如果一行包含......从两行获取数据并将其插入...的开头...对我来说似乎不可能。 我在行搜索结束时尝试了正则表达式,但无法使其正常工作。 我也无法按照我的意愿安排连续循环来在行中插入数据。如果一个循环工作,下一个循环没有,依此类推。我准备一步一步地处理连续的文件,但是两行排除了'问题完全困扰了我。

我能够相对轻松地从这些输出文件中提取其他数据,因为它们是非常有序的文件,但是这个特殊的问题让我很难过。

我修改过的问题是:

我的输入文件包含以下格式的批量数据(+ - 50 - 70行):

1(P1)      3 P.ell    05/0120 W/P068819 0 12.0 98/99  380 380           C03     104          PROCESSED 21/02/16 TIME 22.16.52 KSINA=8

AGE   SPH   %THN  %INC     SV SI   MAI20  HTPC  VIPC   AGE BA  DBH   HT  SPH   CIH% CIV%    CVD BCON    CMAI      C0   C0CAL    SI20
0  1100     .0  89.0%SPH  2  2     .00    .0    .0 20.00  1   .0 17.3    0     .0   .0     .0   .0    .0000    .000    0%      .00
 7   815   25.9    .0      2  2    9.90  75.5  47.2 20.00  1 26.6 17.3  330     .0   .0     .0 13.0    .2099   1.005   .000   17.30
13   550   32.5    .0                                                                                                              
18   330   40.0    .0                                                                                                              
45     0  100.0    .0                                                                                                              
0SQ     -4  -4  -4  = SI20  17 17 17              PLANTN---104 GREEN MEADOWS       MODEL---P.ELLIOTTII MAC MAC   SQ    10 SI20  22.90
HTPC   76  76  76  =MAI20  10 10 10 FROM HTPC                                                                   HTPC 100 MAI20 20.71
VIPC   47  47  47  =MAI20  10 10 10              HTPC/VIPC REGRESSION---P.ELLIOTTII GENERAL 1/83                VIPC 100 MAI20 20.99
                 MAIDBH     0                                                                                                    
                 INMAI==>   0                                                                                                    
0INPUT FOR CALCULATING HTPC & VIPC =  HT  ---- ----                                                                                  

AGE  DBH   HT  VTREE  SPH  BA  TOTAL WS  UTIL    S    A    B    C    D   TCAI CTCAI  TMAI   UCAI CUCAI  UMAI   SCAI CSCAI  SMAI IAGE

1   .0   .2  .0000  979   0      0  0     0    0    0    0    0    0     .0     0    .0     .0     0    .0     .0     0    .0  1.0
2   .0   .9  .0000  979   0      0  0     0    0    0    0    0    0     .0     0    .0     .0     0    .0     .0     0    .0  2.0
3  3.9  2.0  .0007  979   1      1  1     0    0    0    0    0    0     .7     1    .2     .0     0    .0     .0     0    .0  3.0
4  7.1  3.4  .0041  979   4      4  3     1    1    0    0    0    0    3.4     4   1.0     .6     1    .2     .0     0    .0  4.0
5  9.4  4.6  .0102  979   7     10  5     5    5    0    0    0    0    5.9    10   2.0    4.1     5    .9     .0     0    .0  5.0
6 11.3  5.7  .0188  979  10     18  6    12   12    1    0    0    0    8.4    18   3.1    7.5    12   2.0     .0     0    .0  6.0
7 13.0  6.7  .0293  979  13     29  7    22   19    3    0    0    0   10.3    29   4.1    9.7    22   3.1     .0     0    .0  7.0
                   17%                                                                                                           
THN 11.4  6.7  .0230  164   2      4  1     3    2    0    0    0    0                                                              
REM 13.4  6.7  .0315  815  12     26  6    20   17    3    0    0    0                                                              

 8 15.0  7.6  .0453  815  14     37  6    31   21   10    0    0    0   11.2    40   5.0   10.9    33   4.1     .0     0    .0  7.6
 9 16.4  8.5  .0607  815  17     49  6    43   23   20    0    0    0   12.5    52   5.8   12.2    45   5.0     .2     0    .0  8.6
10 17.4  9.4  .0771  815  19     63  7    56   24   30    2    0    0   13.4    66   6.6   13.1    58   5.8    1.3     2    .2  9.6
11 18.3 10.3  .0941  815  21     77  7    70   24   41    5    0    0   13.9    80   7.3   13.6    72   6.5    3.0     5    .4 10.6
12 19.0 11.3  .1118  815  23     91  7    84   24   50   10    0    0   14.4    94   7.8   14.1    86   7.2    5.4    10    .8 11.6
13 19.6 12.2  .1299  815  25    106  8    98   24   56   18    0    0   14.7   109   8.4   14.4   100   7.7    8.0    18   1.4 12.6
                   33%                                                                                                           
THN 17.5 12.2  .1044  265   6     28  2    25    8   15    3    0    0                                                              
REM 20.6 12.2  .1421  550  18     78  5    73   16   42   15    0    0                                                              

14 21.3 13.0  .1636  550  20     90  6    84   16   44   25    0    0   11.8   121   8.6   11.6   112   8.0   10.0    28   2.0 10.4
15 22.0 13.7  .1864  550  21    103  6    97   16   45   36    0    0   12.5   133   8.9   12.3   124   8.3   11.0    39   2.6 11.2
16 22.7 14.5  .2100  550  22    116  6   109   15   46   48    0    0   13.0   146   9.1   12.7   137   8.6   12.0    51   3.2 12.0
17 23.3 15.3  .2345  550  23    129  6   123   15   46   61    0    0   13.5   160   9.4   13.2   150   8.8   12.9    64   3.8 12.8
18 23.9 15.9  .2598  550  25    143  7   136   15   46   74    1    0   13.9   174   9.6   13.6   164   9.1   13.8    78   4.3 13.6
                   40%                                                                                                           
THN 21.6 15.9  .2142  220   8     47  2    45    6   19   20    0    0                                                              
REM 25.3 15.9  .2901  330  17     96  4    92    9   28   54    1    0                                                              

19 26.0 16.6  .3203  330  17    106  4   101    9   27   63    3    0   10.0   184   9.7    9.8   174   9.1   10.5    88   4.6 11.0
20 26.6 17.3  .3519  330  18    116  5   112    9   27   71    5    0   10.4   194   9.7   10.2   184   9.2   10.6    99   4.9 11.7
21 27.2 18.0  .3849  330  19    127  5   122    9   27   80    8    0   10.9   205   9.8   10.7   194   9.3   11.1   110   5.2 12.4
22 27.9 18.7  .4192  330  20    138  5   133    8   26   87   11    0   11.3   216   9.8   11.1   206   9.3   11.5   121   5.5 13.2
23 28.4 19.3  .4546  330  21    150  5   145    8   26   94   16    0   11.7   228   9.9   11.4   217   9.4   11.8   133   5.8 14.0
24 29.0 20.0  .4914  330  22    162  5   157    8   26  101   22    0   12.2   240  10.0   11.9   229   9.5   12.3   145   6.1 14.9
25 29.6 20.6  .5292  330  23    175  6   169    8   25  106   29    0   12.5   253  10.1   12.2   241   9.6   12.6   158   6.3 15.7
26 30.2 21.2  .5682  330  24    188  6   182    8   25  112   37    0   12.9   265  10.2   12.6   254   9.8   13.0   171   6.6 16.5
27 30.7 21.8  .6083  330  25    201  6   194    8   25  115   46    0   13.2   279  10.3   13.0   267   9.9   13.3   184   6.8 17.3
28 31.3 22.4  .6492  330  25    214  7   208    8   24  119   56    1   13.5   292  10.4   13.2   280  10.0   13.6   198   7.1 18.2
29 31.9 23.0  .6908  330  26    228  7   221    8   24  122   65    2   13.7   306  10.5   13.5   293  10.1   13.8   212   7.3 19.0
30 32.4 23.5  .7332  330  27    242  7   235    8   24  123   77    3   14.0   320  10.7   13.7   307  10.2   14.0   226   7.5 19.8
31 33.0 23.9  .7766  330  28    256  7   249    8   24  125   88    5   14.3   334  10.8   14.0   321  10.4   14.3   240   7.7 20.4
32 33.6 24.4  .8202  330  29    271  8   263    8   23  126   99    7   14.4   349  10.9   14.1   335  10.5   14.4   255   8.0 21.0

首先,第一行中的两个变量(1(P1 ...):在这种情况下' C03 104'需要从中提取并发送到OUTPUT。(与上一个问题相同,但输出位置会发生变化。)

其次,所有以' THN'开头的行除了可以丢弃THN之外,需要提取它们。 如果有两个,三个,四个甚至五个等等。' THN'行,它们都需要从批处理中提取并发送到OUTPUT。(+ - 与上一个问题相同)

第三,虽然顺序第二步,但是“年龄”中的最后一个数字。在“THN'之前的主要表格数据的列线,需要附加到提取的THN'在它下面的直线(在这种情况下,图7,13和18)这些需要添加到它们各自的THN线。请参阅下面的预期输出,其中在两个C03 104'之后插入了年龄。每行中的变量。

如果没有' THN'在给定批次中的行,应忽略整个批次,没有输出,并考虑下一批次(以' 1(P1)'再次开始)。

上述批次预期的正确输出是:

 CO3   104     7  11.4  6.7  .0230  164   2      4  1     3    2    0    0    0    0
 CO3   104    13  17.5 12.2  .1044  265   6     28  2    25    8   15    3    0    0
 CO3   104    18  21.6 15.9  .2142  220   8     47  2    45    6   19   20    0    0

从中可以看出,顶行的两个变量是在输出THN数据行的开头插入的。然后将从输入批次中读取的年龄数字插入其各自的THN行,然后附加其余的THN行数据。

我前段时间的努力但没有更新如下:

while ( my $line = <INPUT> ) {

                if($line =~ /\s{6,11}(\w{1}\d{1}\w{0,5})\s{0,5}(\d{3})/) {
                my @c_no = "$1,$2\n";   
                foreach (@c_no) {
                print OUTPUT $_;                    
                }
                if ($line =~ /^(\s{1}THN)(\s{1,3}\d{0,2}.\d)(\s{1,3}\d{0,2}.\d)(\s{1,2}\d{0,1}.\d{4})(\s{1,2}\d{2,4})
                            (\s{2,3}\d{1,2})(\s{1,6}\d{1,4})(\s{1,2}\d{1,2})(\s{1,5}\d{1,4})(\s{1,4}\d{1,4})
                            (\s{1,4}\d{1,4})(\s{1,4}\d{1,4})(\s{1,4}\d{1,4})(\s{1,4}\d{1,4})|(^1(P1))/x){

                print OUTPUT "$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14\n";
                }           
                }
                }

非常感谢建议,指导和帮助。

2 个答案:

答案 0 :(得分:1)

使用split将每一行分隔为以空格分隔的字段更为简单,如果您为标题行中的两个字段维护状态变量,则非常简单,第一个字段完全为数字的任何行的年龄。然后,所有必要的是在以THN

开头的任何行上的数字之前打印这三个值

请注意,最简单的方法是将输入文件的名称作为参数传递给命令行。然后你要做的就是从<>读取。所有的打开和错误处理都已经为您完成了

您要求的输出格式相当深奥。我看不到列宽的任何模式,我必须编写自定义printf格式来重新创建它。如果您需要其他内容,则每个输出行中的所有值都在@data数组中,您可以根据需要使用该数组

use strict;
use warnings 'all';

my ($c1, $c2, $age);

while ( <> ) {

    next unless /\S/;

    my @fields = split;

    if ( $fields[0] eq '1(P1)' ) {
        ($c1, $c2) = @fields[10,11];
    }
    elsif ( $fields[0] !~ /\D/ ) {
        $age = $fields[0];
    }
    elsif ( $fields[0] eq 'THN' ) {
        my @data = ( $c1, $c2, $age, @fields[1..13] );
        printf "%4s %5s %5d %5.1f%5.1f%7.4f%5d%4d%7d%3d%6d%5d%5d%5d%5d%5d\n", @data;
    }
}

输出

 C03   104     7  11.4  6.7 0.0230  164   2      4  1     3    2    0    0    0    0
 C03   104    13  17.5 12.2 0.1044  265   6     28  2    25    8   15    3    0    0
 C03   104    18  21.6 15.9 0.2142  220   8     47  2    45    6   19   20    0    0

答案 1 :(得分:0)

我复制并修改了您的示例数据,因此我们没有进行过非常好的测试。我打印到STDOUT进行测试,但这应该很容易改变。

诀窍是要认识到你已经进行了行匹配,这对于正则表达式以及其他处理很有用,这对于普通的旧代码来说可能更好。因此,构建一个小循环,并以相同的优先级处理这些行(这对于检测文件中的错误非常重要 - 不要试图过多地嵌套)。放入一些状态变量来帮助跟踪接下来发生的事情,并确保适当地重置它们。

另外,我在你的示例代码中注意到的一件事是,如果时间间隔和数字正确的话,你花了很多钱。在这种情况下,这几乎肯定是浪费时间,因为关键是&#34; THN&#34;在线的开头。处理文本的一个技巧是关注你真正需要的东西,并使用.*来处理其他东西。这样,线路噪音或语法错误或一些奇怪的格式化故障不会搞砸你的程序。 (有时候.*变成[^"]*或者其他什么,但你明白了......)

my $line_prefix, $have_age_col, $age_col;
while (<>) {
    if (/^1\(P1\).*\s(?P<two_vars>\w+\s+\w+)\s+PROCESSED .* TIME .* KSINA=.*$/) {
        # Start new section
        $line_prefix = $+{two_vars};
        $have_age_col = 0;
        $age_col = undef;
    }
    if (/^AGE /) {
        $have_age_col = 1;
    }
    if ($have_age_col && /^\s{0,5}(\d+)/) {
        $age_col = substr "    ".$1, -5;
    }
    if (/^THN /) {
        die "THN encountered without header"
            unless $line_prefix;
        die "THN encountered without age column"
            unless $have_age_col and $age_col;

        s/^THN \s*//;
        s/\s+$//;
        my $output = "$line_prefix $age_col $_\n";
        print STDOUT $output;
    }
}