【问题标题】:Perl: how to split a file?Perl:如何拆分文件?
【发布时间】:2012-06-08 21:57:25
【问题描述】:

我需要将一个文件拆分成不同的文件。

示例(原始文件):

*****3123123*****RAW
text1
text2
*****2312354***RAW
text3

期望的输出:

[文件1.txt]

*****3123123*****RAW    
text1
text2

[文件2.txt]

*****312312354***RAW
text3

我尝试使用拆分,但我总是在数组中得到一些额外的白色字符

open FILE, "<file";
@file= <FILE>;
close FILE;
@lines = split (/(RAW\n)/, "@file");
foreach $value (@lines) {
  if ($value =~ /[a-z]|[A-Z]|[1-9]/)  {
    print ("$value\n");
  }
}

输出:

*****3123123*****RAW

 text1
 text2

*****312312354***RAW

 text3

编辑:如果我使用 print ("$value") 而不是 print ("$value\n") 这是输出(注意值之前的 1 个额外空格:

*****3123123*****RAW
 text1
 text2

 *****12354***RAW
 text3

【问题讨论】:

  • 不就是在拆分的时候,并没有去掉换行符,所以当你添加print ("$value\n")的时候,就是多加了一个换行符。这就是为什么它看起来有额外的空白。
  • 没有 \n 我在每个值的开头得到 1 个额外的空格。
  • 额外的空格是因为您将@file 插入到单个字符串中,默认情况下会在元素之间插入一个空格字符。通常最好逐行读取文件,除非它真的很小,但如果你坚持一次读取它,你可以写 @lines = split (/(RAW\n)/, join '', @file 或使用 `my $data = do {local $/; }; @lines = split (/(RAW\n)/, $data;

标签: perl


【解决方案1】:

该程序从RAW 行中提取十进制数并使用它来命名输出文件。它期望输入文件名作为命令行上的参数。

use strict;
use warnings;

@ARGV or die "Input file required as command-line parameter\n";

my $out;

while (<>) {
  if ( /(\d+)\*+RAW$/ ) {
    open $out, '>', "$1.out" or die $!;
    select $out;
  }
  print $_ if $out;
}

【讨论】:

    【解决方案2】:

    使用 line-wise IO 可能会做得更好:

    my $id = 0;
    my $FILE = undef;
    
    while (<>) {
        if (/RAW/) {
            close $FILE if defined $FILE;
            $id++;
            my $path = "File$id.txt";
            open $FILE, '>', $path or die "Could not open $path: $!";
        }
        print $FILE $_ if defined $FILE;
    }
    close $FILE if defined $FILE;
    

    复制并改编自我的一个脚本,该脚本将邮箱文件拆分为每封邮件一个文件。如果第一行与/RAW/ 不匹配,您将不得不修改脚本

    【讨论】:

    • 尝试运行您的脚本,但没有任何反应。脚本开始但永远不会结束,所以我必须 Ctrl-C 它。
    • @user1444482:此解决方案运行良好。它希望像我一样在命令行上输入文件。如果您不提供,它将挂起等待键盘输入。
    • 我并没有真正考虑过。让其他人修复我的代码中的错误?
    【解决方案3】:
    use strictures;
    use File::Slurp qw(read_file write_file);
    my $raw = read_file('raw.txt', binmode => ':raw');
    my $header = qr/^ (?= [*]+ [0-9]+ [*]+ RAW\n)/msx;
    my @chunks = split $header, $raw;
    # (
    #     "*****3123123*****RAW\ntext1\ntext2\n",
    #     "*****2312354***RAW\ntext3"
    # )
    for my $i (1..@chunks) {
        write_file("File$i.txt", {binmode => ':raw'}, $chunks[$i-1]);
    }
    

    【讨论】:

    • 哇,你一定会赢得 Perl 高尔夫,呵呵
    • 这甚至不是高尔夫,这是经验丰富的程序员如何编写的直截了当的 Perl。没有什么晦涩的知识,只是记住内置函数的功能,例如split,并在适当的时候使用CPAN库
    • 因为我必须选择一些理智的东西,以防止复制粘贴编程。我希望我的演示程序以这种方式变得健壮。我不知道文件的实际编码,但这很好,split 也适用于字节语义。 – 想象一下如果我离开 IO 层会发生什么! ☹
    【解决方案4】:

    这就是我想出的。我不禁觉得这是在重新发明轮子。

    #!usr/bin/perl
    my $fi, $fi2;
    my $line;
    my $i;
    my @lines;
    my @filenameparts;
    my $filename = "file_1.txt";
    
    open($fi, "< original.txt");
    @lines = <$fi>;
    open ($fi2, " > $filename");
    
    foreach (@lines)
    {
    if (($i > 0) and $_ =~ /RAW/)
    {
        @filenameparts = split("_", $filename);
        foreach (@filenameparts)
        {
            print "Woooo".$_;
        }
        @filenameparts[1] = substr(@filenameparts[1], 0, @filenameparts[1].length() - 5);
        @filenameparts[1] = ($filenameparts[1] + 1);
        $filename = @filenameparts[0]."_".@filenameparts[1].".txt";
        print $filename;
        close($fi2);
        open ($fi2, " > $filename");
        $i = 0;
        print $fi2 $_;
    
    }
    else
    {
        print $fi2 $_;
    }
    $i++;
    
    }
    

    【讨论】:

    • 您必须养成在 Perl 程序顶部添加use strictuse warnings 的习惯。这将揭示您的编程存在的许多问题,而这些问题在其他情况下并不明显。您还应该记住,您正在编程 Perl 而不是 Java、JavaScript 或 C++ - 无论您来自哪里 - 因为 @filenameparts[1].length() 不会为您提供数组中第二个字符串的长度,它会将第二个字符串与长度连接起来$_ 完全不是一回事。
    • 我非常同意你的观点,我的 Perl 编程很差。
    • 只是想帮助您改进 :) 顺便说一句,我的解决方案比 daxim 的要高得多:P
    【解决方案5】:

    如果您想保留您编写的代码,只需将您的行 print ("$value\n"); 替换为 print ("$value"); 即可...

    或在print 之前删除\nchomp($value); 并保留输出print ("$value\n");

    【讨论】:

      猜你喜欢
      • 2013-02-23
      • 2011-11-12
      • 2013-03-12
      • 1970-01-01
      • 2012-07-14
      • 2021-12-06
      • 2019-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多