0

我想在 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";
}
4

5 回答 5

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::BinarySearch中的bsearch_str_pos函数是对Mastering Algorithms with Perl中的二进制搜索实现的改编。它方便的特点是,如果没有找到搜索字符串,它会返回可以插入的索引点,同时保持排序顺序。

于 2012-08-26T09:17:03.010 回答
1

既然您无论如何都必须阅读文本文件的内容,那么另一种方法怎么样?

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

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

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

于 2012-08-26T05:02:52.987 回答
0

这是一个简单的版本,它从标准输入(或命令行上指定的文件名)读取,如果在输入中找不到,则将“要附加的字符串”附加到输出。输出打印在标准输出上。

#! /usr/bin/perl 

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

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

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

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

于 2012-08-26T09:37:07.870 回答
0

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

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

给予者 alist.txt的上下文是:

ananas
apple
banana
pear

输出是:

ananas
apple
banana
lemon
pear
于 2012-08-26T12:15:45.107 回答
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 <>;
}

基本上与帕维尔的答案相同,除了增加了很多可读性。请注意,它$insert应该已经包含一个尾随换行符。

于 2012-08-26T23:41:17.270 回答