首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >perl使用触发器提取相同分隔符之间的文本

perl使用触发器提取相同分隔符之间的文本
EN

Stack Overflow用户
提问于 2017-01-31 22:12:29
回答 4查看 217关注 0票数 1

我已经能够使用flip-flop来提取文本,在过去我有不同的开始和结束。这一次,我在尝试提取文本时遇到了很多麻烦,因为我的源文件中没有不同的分隔符,因为翻转的开始和结束是相同的。我想让触发器在行号为yyyy时启动true,继续将$_推到一个数组中,直到另一行开始yyyy。触发器的问题是,在我下一次启动时,它将是假的。

代码语言:javascript
复制
while (<SOURCEFILE>) {
  print if (/^2017/ ... /^2017/) 
}

对于给定的源数据,使用上面的代码将会遗漏我也需要匹配的文件的第二个多行部分。也许我认为解析多行文件的最好方法触发器在这种情况下不起作用?我想要做的是从以日期开始的第一行开始匹配,然后继续匹配,直到以日期开始的下一行之前的行。

示例数据如下:

代码语言:javascript
复制
2017 message 1
Text
Text

Text

2017 message 2
more text
more text

more text

2017 message 3
yet more text
yet more text

yet more text

但我得到的是:

代码语言:javascript
复制
2017 message 1
Text
Text

Text

2017 message 2
2017 message 3
yet more text
yet more text

yet more text

...missing消息2内容..

我不能在我的源数据中依赖空格或不同的结束分隔符。我想要的是打印每条消息(实际上是push @myarray, $_ &然后测试匹配),但是这里我遗漏了消息2下面的几行,因为flip被设置为false。有没有办法用flip-flop来处理这个问题,或者我需要使用其他东西?提前感谢任何可以提供帮助/建议的人。

EN

回答 4

Stack Overflow用户

发布于 2017-01-31 22:35:22

这里有一条路要走:

代码语言:javascript
复制
use Modern::Perl;
use Data::Dumper;
my $part = -1;
my $parts;
while(<DATA>) {
    chomp;
    if (/^2017/ .. 1==0) {
        $part++ if /^2017/;
        push @{$parts->[$part]}, $_;
    }
}
say Dumper$parts;

__DATA__
2017 message 1
Text
Text

Text

2017 message 2
more text
more text

more text

2017 message 3
yet more text
yet more text

yet more text

输出:

代码语言:javascript
复制
$VAR1 = [
          [
            '2017 message 1',
            'Text',
            'Text',
            '',
            'Text',
            ''
          ],
          [
            '2017 message 2',
            'more text',
            'more text',
            '',
            'more text',
            ''
          ],
          [
            '2017 message 3',
            'yet more text',
            'yet more text',
            '',
            'yet more text'
          ]
        ];
票数 2
EN

Stack Overflow用户

发布于 2017-01-31 22:22:11

我不知道用flipflop怎么做。我在一年前就试过了。但是和我用一些逻辑做的事情一样。

代码语言:javascript
复制
my $line_concat;
my $f = 0;
while (<DATA>) {
    if(/^2017/ && !$f) {
        $f = 1;
    }

    if (/^2017/) {
        print "$line_concat\n" if $line_concat ne "";
        $line_concat = "";
    }

    $line_concat .= $_ if $f;
}

print $line_concat if $line_concat ne "";
票数 1
EN

Stack Overflow用户

发布于 2017-01-31 22:38:31

正如您所发现的,带有匹配分隔符的触发器不能很好地工作。

您是否考虑过改为设置$/

例如:

代码语言:javascript
复制
#!/usr/bin/env perl
use strict;
use warnings; 

local $/ = "2017 message";
my $count;

while ( <DATA> ) {

    print "\nStart of block:", ++$count, "\n";

    print;

    print "\nEnd of block:", $count, "\n";
}

__DATA__
2017 message 1
Text
Text

Text

2017 message 2
more text
more text

more text

2017 message 3
yet more text
yet more text

yet more text

尽管它并不完美,因为它在分隔符上拆分了文件-这意味着在第一个分隔符之前有一个“位”(所以你得到了4个块)。您可以明智地使用'chomp‘重新拼接它,这将从当前块中删除$/

代码语言:javascript
复制
#!/usr/bin/env perl
use strict;
use warnings; 

local $/ = "2017 message";
my $count;

while ( <DATA> ) {
    #remove '2017 message'
    chomp;
    #check for empty (first) block
    next unless /\S/;
    print "\nStart of block:", ++$count, "\n";
    #re add '2017 message'
    print $/;
    print;

    print "\nEnd of block:", $count, "\n";
}

或者,如果是一个数组数组,每次点击消息时都会更新“target key”,那会怎么样呢?

代码语言:javascript
复制
#!/usr/bin/env perl
use strict;
use warnings; 

use Data::Dumper;

my %messages; 
my $message_id;
while ( <DATA> ) {
   chomp;
   if ( m/2017 message (\d+)/ ) { $message_id = $1 }; 
   push @{ $messages{$message_id} }, $_; 
}

print Dumper \%messages;

注意-我使用散列,而不是数组,因为对于不是连续从零开始的消息排序,这会更健壮一些。(使用这种方法的数组将有一个空的“零”元素)。

注意--它也会有“空的”''元素给你的空行。不过,如果您愿意,您可以过滤这些内容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41959737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档