通过将2个模式之间的行写入新文件,将文件拆分为多个文件

时间:2014-09-11 09:33:28

标签: perl

这是输入文件:

#cat myfile
-- START
whatever
whatever
-- END

-- START
whatever
whatever
-- END

-- START
whatever
whatever
-- END

-- START
whatever
whatever
-- END

我需要抓住-- START-- END之间的行,并将这些行写入单独的文件。所以在这个用例中,我应该创建4个文件,如下所示:

# cat file1
whatever
whatever

# cat file2
whatever
whatever

# cat file3
whatever
whatever

# cat file4
whatever
whatever

这是我的代码:

#!/usr/bin/perl
use strict;
use warnings;

open (my $fh, "<", "/var/tmp/myfile");
my $counter = 0;

while (<$fh>)
{
    if (/START/../END/)
    {
        my $filename = "/var/tmp/file".$counter;
        open (my $oh, ">", $filename);
        print $oh $_;
    }
    $counter++;
}

问题:我的代码正在为-- START-- END

中的每条行创建一个文件

你能帮我弄清楚如何修复这段代码。感谢。

2 个答案:

答案 0 :(得分:2)

不应为每一行打开新文件,而应在每个范围的开头打开它。

使用范围的返回值来确定何时应打开文件并仅打印边界条件之间的那些线。

my $oh;
while (<$fh>) {
    if ( my $range = /START/ .. /END/ ) {
        # Start of Range - Open the file handle
        if ( $range == 1 ) {
            my $filename = "/var/tmp/file" . $counter++;
            open( $oh, ">", $filename ) or die $!;

        # Print until End of Range
        } elsif ( $range !~ /E/ ) {
            print $oh $_;
        }
    }
}

答案 1 :(得分:1)

您可以将输入分隔符设置为&#34; - END&#34;令牌,因此文件以&#34; - END&#34;分隔的块读入。然后可以使用正则表达式捕获所需的信息。我已经注释掉了您的文件I / O行并使用了本地数据,因此您可以运行代码来检查它是否有效:

#!/usr/bin/perl
use strict;
use warnings;
use feature ":5.10";
use Data::Dumper;

#open (my $fh, "<", "/var/tmp/myfile");
my $counter = 0;

$/ = "-- END";
# while (<$fh>)
while (<DATA>)
{   if (/START\s*(\S.+?)\s*-- END/ms)
    {
    #    my $filename = "/var/tmp/file".$counter;
    #    open (my $oh, ">", $filename);
    #    print $oh $1;
        say "file $counter\n$1";
        $counter++;
    }
}

__DATA__

-- START
whatever1
whatever2
-- END

-- START
whatever3
whatever4
-- END

-- START
whatever5
whatever6
-- END

-- START
whatever7
whatever8
-- END

输出(转到STDERR,但显然您取消注释读取和写入文件的行):

file 0
whatever1
whatever2
file 1
whatever3
whatever4
file 2
whatever5
whatever6
file 3
whatever7
whatever8