【问题标题】:PERL:To write in input file (without overwrite the original file)PERL:写入输入文件(不覆盖原始文件)
【发布时间】:2017-08-14 15:31:28
【问题描述】:

下面是我的输入文件以及我的输出文件。需要帮助来读取和写入输入文件。 (PS:输入输出是同一个文件)

 TS_dunit_       PDX_VER_6
 TS_test1_par    PDX_VER_0

我的代码如下所示;

#!/usr/perl/5.14.1

use Getopt::Long;
use strict;
use warnings;

my $file;

GetOptions(
   "iofile=s" => \$file
   );
if (not defined $file){
print "Please specify input_output (iofile) file\n";
exit;
}

open (my $fh, "$file") or die "Can't open the file $file: ";
open (my $fh1, ">>$file") or die "Can't open the file $file: ";

while (<$fh>){
chomp $_;
next if ($_ !~ /S+/);
$_ =~ /(\S+)\s+(\S+)/;
my $first_underscore =index ($1, '_');
my $dev = substr ($1, $first_underscore + 1,
        rindex ($1, '_') - $first_underscore - 1);
my $tag  = $2;
my $cat_path = "/testdata/17.26.6/$dev/sd/$tag";
my $arc_path = "archive/$dev/sd/$tag";
if (-d $cat_path){
            print $fh1 "$dev $tag IN_CAD\n";
    }elsif (-d $arc_path){
            print $fh1 "$dev $tag IN_ARCHIVE\n";
    }else{
            print $fh1 "NA\n";
    }

}
   print "Done! File been append.\n";   

以上代码给出的输出为

  TS_dunit_          PDX_VER_6       
  TS_test1_par       PDX_VER_0        


  IN_CAD 
  IN_CAD 

如果无论如何我可以使输出如下所示,需要帮助。

  TS_dunit_          PDX_VER_6     IN_CAD   
  TS_test1_par       PDX_VER_0     IN_CAD   

【问题讨论】:

  • 一个文件不能被改变以便添加到它的行而不覆盖它。没关系:您根据需要编写输出文件(附加行),然后将其重命名为原始文件。最后,您可以根据需要更改原始文件。 (在一个简单的方法中,inode 号会改变,你在乎吗?)
  • 非常感谢。真的很重视你的建议,我现在正在编码......

标签: perl file


【解决方案1】:

不能在不覆盖文件其余部分的情况下追加到文件中的一行。文件是一个字节序列,我们不能“插入”新的,只能覆盖现有的(或通过扩展文件添加更多)。例如,请参阅this post 了解更多详情。

相反,写出一个新文件,然后将其重命名为原始文件。这确实改变了 inode 号;如果你需要保持它看到最后。该代码通过正则表达式简化了index+substr 部分。

use warnings;
use strict;
use feature 'say';
use File::Copy qw(mv);

# ... code from the question 

open my $fh,     '<', $file    or die "Can't open $file:$!";
open my $fh_out, '>', $outfile or die "Can't open $outfile:$!";

while (<$fh>) 
{
    next if not /\S/;
    chomp;

    my ($dev, $tag) = /.*?_(.*)_\s+(.*)/;

    my $cat_path = "/testdata/17.26.6/$dev/sd/$tag";
    my $arc_path = "archive/$dev/sd/$tag";

    if (-d $cat_path) {
        say $fh_out "$_ IN_CAD";
    } 
    elsif (-d $arc_path) {
        say $fh_out "$_ IN_ARCHIVE";
    }
    else {
        say $fh_out "NA";
    }
}
close $fh;
close $fh_out;

# Changes inode number. See text for comment
move($fh_out, $fh) or die "Can't move $fh_out to $fh: $!";

正则表达式匹配第一个_,因为? 使.*? 非贪婪(它在第一个_ 处停止)。然后它会捕获直到 last _ 的所有内容,因为 .* 是贪婪的,匹配所有内容直到最后一个 _。这就是问题中的代码所做的,使用rindex。然后它会捕获所有制表符/空格之后的内容。

然后将当前行打印附加到输出文件中,就像问题中一样。由于输出文件是临时的,它的名称应该使用File::Temp 构建。然后使用File::Copy重命名文件。

这会更改 inode 编号。如果这很重要,保持 inode 编号的一种方法如下。输出文件被写出后打开原始文件,什么会破坏它。然后从输出文件中读取并写入原始文件。内容被复制到同一个 inode。完成后删除输出文件。在开头链接的帖子中查看更多详细信息。

【讨论】:

  • @Perlnewbie Great :) 如果有问题请告诉我
猜你喜欢
  • 2012-04-19
  • 1970-01-01
  • 2023-03-28
  • 2011-05-08
  • 1970-01-01
  • 2012-04-15
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多