-2

無知で申し訳ありませんが、私は Perl に非常に慣れていないため、すぐに支援が必要です....

「履歴」データを含むファイルがあり、レコードがコンマで区切られていることがわかっています。もちろん、このファイルは歴史が進むにつれてどんどん大きくなっていきます。そこで、Perl を使用して、データのファイルが最も古いので、そのファイルを切り詰めたいと考えています。これは正確な科学である必要はありません。私は次のようなことをするだろうと考えました:

  • ファイル内のカンマの数を数え、2 で割ります (中間点を見つけるため)。
  • たとえば、100 件のレコードがある場合 (つまり、99 個のカンマ区切り)、カンマ数は 99 個です。
  • 次に、2 で割っておおよその中間点 (切り上げ) を取得します。この例では 46 になります。
  • 次に、46 番目のカンマより前のすべてのレコードを削除します (ファイルがカンマで始まらないように、カンマを含みます)。
  • そして、新しく整理した履歴データ ファイルを保存します。

以下は、カンマ区切りを使用した非常に小さなサンプル ファイル レイアウトです。

20121130092403000Server1::RedHat   1.2.3.4(1234),20121130092503000Server2::RedHat   5.6.7.8(1234),20121130092603000Server3::SUSE   9.8.7.6(9876),20121130092703000Server4::WindowsXP   5.6.7.8(6543)

これが理にかなっていることを願っています。

ありがとう!

4

4 に答える 4

1

「最速で最も効率的な方法」とは何かは別の問題かもしれません。これは、次のようなことを行う典型的な方法です。

use strict;
use warnings;

local $/ = ",";
my @file = <DATA>;
say "Number of records: " . @file;
my $half = int((@file/2)+0.5);
say "Last half of records ($half):";
say @file[$half .. $#file];

__DATA__
20121130092403000Server1::RedHat   1.2.3.4(1234),20121130092503000Server2::RedHat   5.6.7.8(1234),20121130092603000Server3::SUSE   9.8.7.6(9876),20121130092703000Server4::WindowsXP   5.6.7.8(6543),

ここでは、デモンストレーションに DATA ファイル ハンドルが使用されていることに注意してください。代わりにファイル引数を使用するように変更<DATA>するだけです。<>

ファイルがメモリに読み込まれるため、これはやや効率が悪く、大きなファイルの場合はコストがかかる可能性があるメモリを消費します。別の方法としては、単純にファイル全体を実行してレコードを数えてから、ファイルを再度開いて印刷を行うという方法があります。例えば:

my $file = shift;
local $/ = ",";
open my $fh, "<", $file or die $!;
my $count;
while (<$fh>) { $count++ }
$count = int(($count/2)+0.5);
open $fh, "<", $file or die $!;
while ($count-- > 0) { <$fh> };
while (<$fh>) { print }

もちろん、これらの出力は次のようにリダイレクトする必要があります。

perl script.pl oldfile > newfile

Tie::Fileモジュールも気に入るかもしれません。例えば:

use strict;
use warnings;
use Tie::File;

my $file = shift;
tie @array, 'Tie::File', $file or die $!;
my $half = int((@array/2)+0.5);
splice @array, 0, $half;
untie @array;

この影響は元に戻せないので、試す前にバックアップを作成してください。大きなファイルでも効率的であると思われ、ファイルをメモリに読み込みません。

于 2012-12-11T19:33:43.433 に答える
0

ファイルの先頭から削除することはできません。ファイルの終わりからのみです。ファイルの先頭から効果的に削除するには、ファイル全体を書き直す必要があります (たとえば、保持する部分を含む新しいファイルを作成し、新しいファイルの名前を古いファイルの上に変更します)。

于 2012-12-11T19:07:50.423 に答える
0

ファイルにデータを追加する方法とタイミングに大きく依存します。データの追加は1日1回ですか?1時間に1回?継続的に?手動で?データ ファイルを再構築している間、新しいデータがファイルに追加されるのを防ぐことができますか? ファイルは、書き込みプロセスによって継続的に開いたままになりますか、それとも新しいデータが追加されるたびに再度開かれますか?

より良いアプローチは、新しいデータを新しいファイルに書き込むことです。たとえば、データを 1 日単位で管理する場合は、現在の日付に基づいて新しいデータをファイルに書き込むライター プロセスを作成します。たとえば、2012-12-11 に書き込まれたデータは、ファイルdata-2012-12-11などに書き込まれます。

その後、ファイルを削除するだけでデータを管理できます。すべてのデータを繰り返し処理するには、perl のグロビング機能を使用できます。

@ARGV = glob("data-*");
while (<>) {
  ...
}
于 2012-12-11T19:34:23.180 に答える
0

すべてのレコードが 1 行 (.csv がリストに似ている) にあるか、複数行 (.csv がテーブルに似ている) にあるかによって異なります。

前者の場合、概説したアプローチはうまく機能します。これはトリックを行います:

use strict;
use POSIX;

my $filename = "somecsvfilename.csv";
open (IN, "<", $filename);
my $fulltext;
while (<IN>) {
    chomp;
    $fulltext .= $_;
}
close IN;

my @data_segments = split(",", $fulltext);
my $num_commas = @data_segments;
my $num_to_delete = floor($num_commas/2);

open (OUT, ">", $filename);
my $i = $num_to_delete;
while ($i < $num_commas) {
    print OUT $data_segments[$i];
    if ($i != ($num_commas - 1)) {print OUT ","}
    $i++;
}
close OUT;

データが実際にテーブルである場合は、Text::CSV のようなものを使用して、データを出力する前に行配列の前半を削除するだけです。ヘッダーデータが含まれている可能性があるため、最初の行を保持することを検討することをお勧めします...入力を確認しないと、何が最適かを判断するのは困難です。

于 2012-12-11T19:36:39.240 に答える