Perl如何将文本文件分割成块?

3

我有一个由成千上万篇文章组成的大型txt文件,我正在尝试将其拆分为单独的文件 - 每个文章都保存为article_1、article_2等。每篇文章都以包含单词/DOCUMENTS/的行开头。 我完全不懂perl,任何见解都会很棒!(甚至是关于好文档网站的建议)。非常感谢。 到目前为止,我尝试的代码如下:

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

my $id = 0;
my $source = "2010_FTOL_GRbis.txt";
my $destination = "file$id.txt";

open IN, $source or die "can t read $source: $!\n";

while (<IN>)
  {
    {  
      open OUT, ">$destination" or die "can t write $destination: $!\n";
      if (/DOCUMENTS/)
       {
         close OUT ;
         $id++;
       }
    }
  }
close IN;

2
我试图重新缩进你粘贴的内容,并且我看到了一对多余的 { }。你确定你已经粘贴了整个东西吗?另外,下次在问题/答案中粘贴代码时,请使用“{ }”按钮。 - ArjunShankar
2个回答

4
假设/DOCUMENTS/出现在单独的一行上,那么你可以将其作为记录分隔符
use English     qw<$RS>;
use File::Slurp qw<write_file>;
my $id     = 0;
my $source = "2010_FTOL_GRbis.txt";

{   local $RS = "\n/DOCUMENTS/\n";
    open my $in, $source or die "can t read $source: $!\n";
    while ( <$in> ) { 
        chomp; # removes the line "\n/DOCUMENTS/\n"
        write_file( 'file' . ( ++$id ) . '.txt', $_ );
    }
    # being scoped by the surrounding brackets (my "local block"),
    close $in;    # an explicit close is not necessary
}

注:

  • use English 声明了全局变量$RS,它的“混乱名称”是$/。请参见perldoc perlvar
  • 行分隔符是记录(record)分隔符的默认值。也就是说,文件读取的标准单位是记录,默认情况下仅仅是一行。
  • 正如您在链接文档中发现的那样,$ RS 仅接受文本字符串。 因此,根据文章之间的分割是独立的一行 '/DOCUMENTS/',我指定了 newline + '/DOCUMENTS/' + newline。 如果这是在某一行上出现的路径的一部分,则该特定值将无法用作记录分隔符。

非常感谢您的回复。您能解释一下记录分隔符是如何工作的吗?我需要先声明变量RS吗? - user1562471
@user1562471,请查看备注部分,刚刚添加。 - Axeman
再次感谢。DOCUMENTS不会单独出现在一行中,而是作为表达式的一部分,例如“150个DOCUMENTS中的1个”,因此它不能作为记录分隔符。但我会尝试找到另一个整行的分隔符。 - user1562471
太好了!非常感谢。我找到了另一个分隔符,它完美地工作了。 - user1562471

2
你读过 Programming Perl 吗?这是最好的入门书籍!
我不明白你试图做什么。我猜你有一些包含文章的文本,并想将所有文章分别保存到不同的文件中。
use warnings;
use strict;
use autodie qw(:all);

my $id          = 0;
my $source      = "2010_FTOL_GRbis.txt";
my $destination = "file$id.txt";

open my $IN, '<', $source;
#open first file
open my $OUT, '>', $destination;

while (<$IN>) {
    chomp;    # kill \n at the end
    if ($_ eq '/DOCUMENTS/') {  # not sure, am i right here or what you looking for
        close OUT;
        $id++;
        $destination = "file$id.txt";
        open my $OUT, '>', $destination;
    } else {
        print {$OUT} $_, "\n";     # print into file with $id name (as you open above)
    }
}
close $IN;

您可以刪除對 my $destination 的第一個賦值。此外,我認為 OP 指的是字符串 /DOCUMENTS/(作為文件系統中路徑的一部分)是新文章標題行的一部分,因此您最好說 if (m{/DOCUMENTS/}) { - simbabque
你是对的,“DOCUMENT”是每篇文章标题的一部分。但是上面的脚本不起作用,循环不起作用,我只得到一个名为file0.txt的文件,里面包含了所有的文章。 - user1562471

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接