Perl:如何在已排序的文本文件中添加一行

时间:2012-08-26 04:53:54

标签: perl file

我想在perl中的文本文件中添加一行,其中包含排序形式的数据。我已经看到了一些示例,它们展示了如何在文件末尾附加数据,但由于我希望数据采用排序格式。

请指导我怎么做。

基本上从我到目前为止所做的尝试: (我打开一个文件,grep它的内容,看看我想要添加到文件的行是否已经存在。如果它确实比退出,则将其添加到文件中(这样数据保持排序格式)

open(my $FH, $file) or die "Failed to open file $file \n";
@file_data = <$FH>;
close($FH);
my $line = grep (/$string1/, @file_data);
if($line) {
   print "Found\n";
   exit(1);
}
else
{
  #add the line to the file
  print "Not found!\n";
}

5 个答案:

答案 0 :(得分:3)

以下是使用Tie::File的方法,以便您可以轻松地将文件视为数组,List::BinarySearchbsearch_str_pos函数可以快速找到插入点。找到插入点后,检查该点的元素是否等于插入字符串。如果不是,splice进入数组。如果它相等,请不要将其拼接。然后使用untie完成,以便文件干净地关闭。

use strict;
use warnings;
use Tie::File;
use List::BinarySearch qw(bsearch_str_pos);

my $insert_string = 'Whatever!';
my $file          = 'something.txt';

my @array;
tie @array, 'Tie::File', $file or die $!;

my $idx = bsearch_str_pos $insert_string, @array;

splice @array, $idx, 0, $insert_string
    if $array[$idx] ne $insert_string;

untie @array;

来自List::BinarySearchbsearch_str_pos函数是Mastering Algorithms with Perl的二进制搜索实现的改编版。其方便的特点是,如果找不到搜索字符串,它将返回可以插入的索引点,同时保持排序顺序。

答案 1 :(得分:1)

既然你必须阅读文本文件的内容,那么不同的方法呢?

逐个读取文件中的行,与目标字符串进行比较。如果您读取的行等于目标字符串,则无需执行任何操作。

否则,您最终会根据排序条件读取比当前行“更大”的行,或者您点击文件的末尾。在前一种情况下,您只需将字符串插入该位置,然后复制其余行。在后一种情况下,您将字符串追加到末尾。

如果您不想这样做,可以在@file_data中进行二进制搜索,找到添加行的位置,而不必检查所有条目,然后将其插入到数组中在将数组输出到文件之前。

答案 2 :(得分:0)

这是一个从stdin(或命令行中指定的文件名)读取的简单版本,如果在输入中找不到,则将'string追加'到输出中。输出打印在标准输出上。

#! /usr/bin/perl 

$found = 0;
$append='string to append';

while(<>) {
    $found = 1 if (m/$append/o);
    print
}

print "$append\n" unless ($found);;

修改它以就地编辑文件(使用perl -i)并从命令行获取追加字符串非常简单。

答案 3 :(得分:0)

在不使用任何模块的情况下插入线条的“简单”单行可以是:

perl -ni -le '$insert="lemon"; $eq=($insert cmp $_); if ($eq == 0){$found++}elsif($eq==-1 && !$found){print$insert} print'

给予list.txt,其背景为:

ananas
apple
banana
pear

输出是:

ananas
apple
banana
lemon
pear

答案 4 :(得分:0)

{
  local ($^I, @ARGV) = ("", $file); # Enable in-place editing of $file

  while (<>) {
    # If we found the line exactly, bail out without printing it twice
    last if $_ eq $insert;
    # If we found the place where the line should be, insert it
    if ($_ gt $insert) {
      print $insert;
      print;
      last;
    }
    print;
  }
  # We've passed the insertion point, now output the rest of the file
  print while <>;
}

除了添加了大量可读性之外,与pavel的答案基本相同。请注意,$insert应该已经包含一个尾随换行符。