2

私はPerlを使用して、次のような繰り返しセクションを持つファイルを解析しようとしています。

システム:server1.domain.com
開始時間:20121021T01:00:56
停止時間:20121021T01:00:56
戻りコード:0

出力
------
user1
user2
user3

##############################

システム:server2.domain.com
開始時間:20121021T01:00:56
停止時間:20121021T01:00:56
戻りコード:0

出力
------
user1
user4
user5
user6

入力レコード区切り文字を「##############################」に設定できます。これにより、各ブロックが次のようになります。別のレコード。

ただし、各サーバーのキーとしてユーザー名をハッシュに入力できる必要があります。

これを達成するための最良の方法は何ですか?

4

3 に答える 3

1

Perl のリファレンスを調べる必要があります。

Perl プレリリース 5.0 では、3 種類のデータ構造があり、それらにはスカラー データしか格納できませんでした。たとえば、ハッシュを使用できますが、ハッシュの各値は文字列または数値である可能性があります。

Perl 5.0 で参照が導入されました。参照は、別のデータ構造を指すデータの一部です。たとえば、サーバーを表すハッシュを持つことができます。ハッシュの各メンバーは、ユーザー (または必要に応じてユーザーのリスト) を含む別のハッシュを指します。

たとえば、次のようなハッシュがあります。

$system{server1.domain.com}  --->  $anon_array[0] = "user1"
                                   $anon_array[1] = "user2"
                                   $anon_array[2] = "user3"

$system{server2.domain.com}  ----> $another_anon_array[0] = "user1"
                                   $another_anon_array[1] = "user2"
                                   $another_anon_array[2] = "user3"
                                   $another_anon_array[3] = "user4"

上記で、%systemハッシュのキーが、ユーザーのリストを含むメモリ内の配列を実際に指していることがわかります。@fooこれらの配列には、やなどの名前はありません@bar。それらにアクセスできる唯一の方法は、%systemハッシュを使用することです。したがって、それらは無名配列として知られています。

参照を作成するには、変数の前にバックスラッシュを置きます。

$my_reference = \%my_hash

ここで、 hashのメンバー$my_referenceを指します。再びハッシュへの参照を作成したい場合は、その前にハッシュ記号 ( ) を付けます。%my_hash%

%bar = %{$my_reference};

次の構文を使用して->、何かが参照を指していることを示すことができます。

$foo->[0];   Points to the first member of an anonymous array.

$bar = [];    #Sets $bar to be a reference to an anonymous array
$foo = {};    #Sets $foo to be a reference to an anonymous hash.

さあ、本当の楽しみが始まります!個々の値を保存する代わりに、データ構造全体を保存できるようになりました。

次のようなものを想像してください。

my %system;   #Normal hash keyed by domain name

$system{server1} = {};  # This points to an anonymous hash!
$system{server1}->{START}  = "20121021T01:00:56";
$system{server1}->{STOP}   = "20121021T01:00:56";
$system{server1}->{RETURN} = 0;
$system{server1}->{USERS} = [];  #This hash entry points to an anonymous array
$system{server1}->{USERS}->[0] = "user1";
$system{server1}->{USERS}->[1] = "user2";
$system{server1}->{USERS}->[2] = "user3";

などですserver2%systemドメイン名をキーとするハッシュが 1 つあります。%systemハッシュ内の各ドメインには、そのシステムSTARTの時刻STOPRETURN値、リストがありUSERSます。の開始時間はserver1? です$system{server1}->{START}。のユーザーのリストは何system2ですか? これ@{ $system{server2}->{USERS} }は ( に格納されている配列の逆参照$system{server2}->{USERS}) です。

この新しい考え方に慣れるには多少時間がかかりますが、データを 1 つの構造としてまとめるのに役立つことがわかります。

もちろん、複雑なデータ構造には、それをまっすぐに保つという問題が伴います。例えば:

use strict;
use warnings;

my %server;
$servre{domain1} = "10.10.1.20";

を宣言したことがないため、失敗し$servreます。でも:

use strict;
use warnings;
my $hash = {};
$hash->{SERVRE}->{domain1} = "10.10.1.20";

うまくいきます。この場合、SERVREは変数ではなく、ハッシュ参照へのキーです。このuse strict;場合、プラグマは私のスペルミスを検出しません。これにより、次のステップであるオブジェクト指向 Perl に進みます。ただし、まずこれらの新しい複雑なデータ構造とその仕組みを理解してください。プログラムでそれらをより快適に使用できるようになったら、オブジェクト指向プログラミングが、それらが引き起こす混乱をどのように緩和するのに役立つかを調べ始めることができます。

于 2012-10-23T02:53:53.447 に答える
1

これをやってみてください:

use strict; use warnings;
use Data::Dumper;          # one of the top 5 modules you should know

my $hash_of_hashes = {};   # a reference to a void HASH

my $current;

while (<>) {
    chomp;
    if (/^System:\s+(.+)/) {
        $current = $1;
    }
    elsif (/^([^:]+):(.+)/) {
        $hash_of_hashes->{$current}->{$1} = $2;
    }
}

print Dumper $hash_of_hashes; # Dumper is a function of Data::Dumper module
# it prints all the data structure in a human readable way

それを使用するには:

perl script.pl input_file.txt

ノート

System:行は常に現在のホストの最初の行と一致すると仮定します。

于 2012-10-23T01:05:28.110 に答える