1

我从 Perl 开始,并在一个 while 循环中逐行解析一些文本,但在这个特定问题上找不到帮助。我想在当前文本行中使用来自先前阅读的文本行的信息。

我的代码如下:

while(<data>){

    my $message = substr $_, 0, 1;

    if ($message eq 'A'){

        my $order_ref  = substr $_,  1, 9;
        my $order_book = substr $_, 20, 6;

        push @add_orders, $_;
        print add_order_file "$order_ref,$order_book\n";
    }
    if ($message eq 'X'){

        my $order_ref = substr $_, 1, 9;
        #now I would like to use order_ref to look up order_book from a previous line of text 
        # where the message is equal to A, 
        my $order_book = LOOKED UP VALUE FROM PREVIOUS TEXT;

        push @add_orders, $_;
        print add_order_file "$order_ref,$order_book\n";
    }
}

“A”消息总是在“X”消息之前,所以我确定如果我看到带有 order_ref 编号的 X 条目,我会向后滚动并找到关联的 A 消息,我可以在其中提取 order_book 变量。我意识到这将涉及某种正则表达式,但我不知道如何让 Perl 只搜索前几行。谢谢!

编辑:我应该更清楚这一点。“A”消息在“X”消息之前,但它们都可以有不同的 order_refs,因此数据如下所示:

A order_ref1, order_book1
A order_ref2,order_book2
A order_ref3,order_book1
X order_ref2 
X order_ref1

对于 X 订单,我想使用 order_ref2 和 order_ref1 查找 order_book。

4

2 回答 2

5

随着您对整个问题的重新定义,需要一个新的答案。

您需要将 order_refs 存储在哈希中,以供以后查找。这个变量需要在while循环外声明。

请注意,我已更改您substr呼叫中的数字以匹配您的示例输入。如果您分享有关如何构造输入行的一些信息,可能会有更好的方法来提取不同的值。使用substr假定固定宽度类型的数据。

use strict;
use warnings;

my %order_book;  # your lookup hash
my @add_orders;
while (<DATA>) {
    chomp;
    my $message = substr $_, 0, 1;

    if ($message eq 'A' or $message eq 'X') {

        my $order_ref = substr $_, 2, 10;
        if ($message eq 'A') {

            $order_book{$order_ref} = substr $_, 13;
        }
        push @add_orders, $_;
        print "$order_ref,$order_book{$order_ref}\n";
    }
}

__DATA__
A order_ref1,order_book1
A order_ref2,order_book2
A order_ref3,order_book1
X order_ref2 
X order_ref1
X order_ref3

输出:

order_ref1,order_book1
order_ref2,order_book2
order_ref3,order_book1
order_ref2,order_book2
order_ref1,order_book1
order_ref3,order_book1
于 2012-09-04T14:40:58.497 回答
0

TLP 的答案已经是正确的。以下是对您的代码的更多建议:

use strict; use warnings;
my @add_orders;
my $last_order_book;
while (my $line = <DATA>) {
  my $message = substr $line, 0, 1;

  if ( $message eq "A" ) {
    my $order_ref  = substr $line, 1,  9;
    my $order_book = $last_order_book = substr $line, 20, 6;

    push( @add_orders, $line );
    print "$order_ref,$order_book\n";
  }
  elsif ( $message eq "Q" ) {
    # Stuff happening ...
  }
  elsif ( $message eq "X" ) {
    my $order_ref = substr $line, 1, 9;

    my $order_book = $last_order_book;

    push( @add_orders, $line );
    print "$order_ref,$order_book\n";
  }
}

__DATA__
A123456789012345678901234567890
XLine XLine XLine XLine XABCDEF

我已经更改了代码中的一些内容。

首先,让我们回答您的问题$order_book:如果您不想使用循环内的变量,您可以添加一个范围在块之外的变量来存储您的变量。我命名它$last_order_book。它会记住零件的最后一次看到的值"A"。请注意,您可以通过像my $foo = my $bar = "baz".

现在我的建议:

  • 总是use strictuse warnings。我不知道你有没有,但我会说,以防万一。
  • 你用$_了很多。我相信,如果您必须经常明确地使用它,那么您实际上应该给它一个名称并改用它。它将使您免于理解以后发生的事情的麻烦。
  • 每行只能有一种,因此拥有多个构造$message没有意义。if {}相反,使用if {} elsif {}它们并按每种行出现的次数对其进行排序。if这将节省时间,因为一旦找到条件之一,它就会停止执行整个-construct。如果您要处理大量数据,这很有用,但始终以这种方式处理并没有什么坏处。为了更清楚,我添加了一个$message eq "Q"案例。
于 2012-09-04T14:54:30.737 回答