使用perl将内容从一个文件复制到另一个文件

时间:2018-02-10 10:08:19

标签: perl copy

以下代码用于将文件内容从readfile复制到writefile。我想复制一些关键字,而不是复制到最后。

use strict;
use warnings;

use File::Slurp;

my @lines = read_file('readfile.txt');

while ( my $line = shift @lines) {
  next unless ($line =~ m/END OF HEADER/);
  last; # here suggest some other logic 
}

append_file('writefile.txt', @lines);

2 个答案:

答案 0 :(得分:5)

next将继续循环的下一次迭代,有效地跳过该循环的循环中的其余语句(在本例中为last)。

last将立即退出循环,这听起来像你想要的。所以你应该能够简单地将条件语句放在last

另外,我不确定你为什么要将整个文件读入内存以迭代它的行?为什么不使用常规while(<>)?我建议避免File::Slurp,它有一些long-standing issues

您没有显示任何带有预期输出的示例输入,并且您的描述不清楚 - 您说&#34;我想复制一些关键字&#34; 但是在您的代码中您使用shift,它会从数组的开头中删除项目。

是否要删除之后的 }?

此代码仅复制标题:

"END OF HEADER"

如果您要复制标题后的所有内容,则可以将上面的use warnings; use strict; my $infile = 'readfile.txt'; my $outfile = 'writefile.txt'; open my $ifh, '<', $infile or die "$infile: $!"; open my $ofh, '>', $outfile or die "$outfile: $!"; while (<$ifh>) { last if /END OF HEADER/; print $ofh $_; } close $ifh; close $ofh; 替换为:

while

在看到while (<$ifh>) { last if /END OF HEADER/; } while (<$ifh>) { print $ofh $_; } 之前,它会循环播放并执行任何操作,然后跳出第一个循环并移动到第二个循环,打印出标题后面的行。

答案 1 :(得分:1)

data.txt中:

fsffs
sfsfsf 
sfSDFF
END OF HEADER 
{ dsgs xdgfxdg zFZ } 
dgdbg 
vfraeer 

代码:

use strict;
use warnings; 
use 5.020;
use autodie;
use Data::Dumper;

my $infile = 'data.txt';
my $header_file = 'header.txt';
my $after_header_file = 'after_header.txt';
open my $DATA, '<', $infile;
open my $HEADER, '>', $header_file;
open my $AFTER_HEADER, '>', $after_header_file;

{
    local $/ =  "END OF HEADER";

    my $header = <$DATA>; 
    say {$HEADER} $header;

    my $rest = <$DATA>;
    say {$AFTER_HEADER} $rest;
}


close $DATA;
close $HEADER;
close $AFTER_HEADER;

say "Created files: $header_file, $after_header_file";

输出:

$ perl 1.pl 
Created files: header.txt, after_header.txt

$ cat header.txt 
fsffs
sfsfsf 
sfSDFF
END OF HEADER

$ cat after_header.txt 

{ dsgs xdgfxdg zFZ } 
dgdbg 
vfraeer 

$/指定输入记录分隔符,默认情况下是换行符。因此,当您从文件中读取时:

while (my $x = <$INFILE>) {

}

$ x的每个值是一系列字符,包括输入的记录分隔符,即换行符,这是我们通常认为的文件中的一行文本。通常,我们会在文本末尾选择newline / input_record_separator:

while (my $x = <$INFILE>) {
    chomp $x;
    say "$x is a dog";
}

但是,您可以将输入记录分隔符设置为您想要的任何内容,例如“END OF HEADER”文本。这意味着一行将是所有文本,包括输入记录分隔符,在这种情况下是“END OF HEADER”。例如,一行将是:“abc \ ndef \ nghi \ nEND OF HEADER”。此外,chomp()现在将从其参数的末尾删除“END OF HEADER”,因此如果您不想在输出文件中使用“END OF HEADER”标记,则可以选择行。

如果perl找不到输入记录分隔符,那么perl会一直读取文件,直到perl命中文件末尾,然后perl返回所有已读取的文本。

当您想要查找文件中的某些特定文本时,可以使用这些操作。

将变量声明为local会使变量变得神奇:当遇到周围块的结束大括号时,perl会将变量设置回打开周围街区的支撑:

#Here, by default $/ = "\n", but some code out here could have
#also set $/ to something else

{
    local $/ =  "END OF HEADER";


} # $/ gets set back to whatever value it had before this block

当你改变perl的预定义全局变量之一时,只要你需要使用变量就可以改变变量,然后将变量改回原来的变量,这被认为是一种好习惯。

如果你只想在大括号之间定位文字,你可以这样做:

data.txt中:

fsffs
sfsfsf 
sfSDFF
END OF HEADER { dsgs xdgfxdg zFZ } 
dgdbg 
vfraeer 

代码段:

    ...
    ...
    {
        local $/ = 'END OF HEADER {';
        my $pre_brace = <$DATA>; 

        $/ = '}';
        my $target_text = <$DATA>;
        chomp $target_text;  #Removes closing brace
        say "->$target_text<-";
    }

--output:--
-> dsgs xdgfxdg zFZ <-