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::BinarySearchの関数を使用するアプローチを次に示します。bsearch_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のバイナリ検索実装を適応させたものです。その便利な特徴は、検索文字列が見つからない場合、ソート順を維持しながら挿入できるインデックス ポイントを返すことです。

于 2012-08-26T09:17:03.010 に答える
1

とにかくテキストファイルの内容を読まなければならないので、別のアプローチはどうですか?

ターゲット文字列と比較して、ファイル内の行を1つずつ読み取ります。ターゲット文字列に等しい行を読み取る場合は、何もする必要はありません。

それ以外の場合は、最終的に、ソート基準に従って現在の行よりも「大きい」行を読み取るか、ファイルの終わりに到達します。前者の場合、その位置に文字列を挿入してから、残りの行をコピーします。後者の場合、文字列を最後に追加します。

そのようにしたくない場合は、バイナリ検索を実行して、@file_dataすべてのエントリを調べることなく行を追加する場所を見つけ、配列をファイルに出力する前に配列に挿入できます。

于 2012-08-26T05:02:52.987 に答える
0

モジュールを使用せずに行を挿入する「単純な」ワンライナーは次のようになります。

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

list.txtコンテキストが次のギバー a :

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 <>;
}

多くの読みやすさが追加されていることを除いて、本質的にpavelの回答と同じです。$insert末尾の改行が既に含まれている必要があることに注意してください。

于 2012-08-26T23:41:17.270 に答える
0

標準入力 (またはコマンド ラインで指定されたファイル名) から読み取り、入力に見つからない場合は「追加する文字列」を出力に追加する単純なバージョンを次に示します。出力は stdout に出力されます。

#! /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 に答える