0

私は perl にまったく慣れていないので (一般的にはプログラミングが得意です)、perl スクリプト (Id_script3.pl) を提示されました。

Id_script3.pl からの問題のコード:

# main sub 
{ # closure 
# keep %species local to sub-routine but only init it once 
my %species; 
sub _init { 
    open my $in, '<', 'SpeciesId.txt' or die "could not open SpeciesId.txt: $!"; 
    my $spec; 
    while (<$in>) { 
        chomp; 
        next if /^\s*$/; # skip blank lines 
        if (m{^([A-Z])\s*=\s*(\d+(?:\.\d)?)(?:\s+AND\s+(\d+(?:\.\d)?))?$}) { 
            # handle letter = lines 
            $species{$spec}{$1} = [$2]; 
            push @{$species{$spec}{$1}}, $3 if $3; 
        } else { 
            # handle species name lines 
            $spec = $_; 
            $len = length($spec) if (length($spec) > $len); 
        } 
    } 
    close $in; 
} 
sub analyze { 
    my ($masses) = @_; 
    _init() unless %species; 
    my %data; 
    # loop over species entries 
SPEC: 
    foreach my $spec (keys %species) { 
        # loop over each letter of a species 
LTR: 
        foreach my $ltr (keys %{$species{$spec}}) { 
            # loop over each mass for a letter 
            foreach my $mass (@{$species{$spec}{$ltr}}) { 
                # skip to next letter if it is not found 
                next LTR unless exists($masses->{$mass}); 
            } 
            # if we get here, all mass values were found for the species/letter 
            $data{$spec}{cnt}++; 
        } 
    }

スクリプトには変更が必要です。現在スクリプトで使用されている「SpeciesId.txt」の代わりに「SpeciesId3.txt」が使用されます。

2 つのファイルにはわずかな違いがあるため、スクリプトを機能させるには、スクリプトにわずかな変更を加える必要があります。違いは、SpeciesId3.txt には文字 (A =、B =、C =) が含まれておらず、元の「SpeciesId.txt」と比較して値のリストが (はるかに) 長いだけです。

SpeciesId.txt:

African Elephant

B = 1453.7
C = 1577.8
D = 2115.1
E = 2808.4
F = 2853.5 AND 2869.5
G = 2999.4 AND 3015.4

Indian Elephant

B = 1453.7
C = 1577.8
D = 2115.1
E = 2808.4
F = 2853.5 AND 2869.5
G = 2999.4 AND 3015.4

Rabbit

A = 1221.6 AND 1235.6
B = 1453.7
C = 1592.8
D = 2129.1
E = 2808.4
F = 2883.5 AND 2899.5
G = 2957.4 AND 2973.4

SpeciesID3.txt (使用するファイル/変更するスクリプト:)

African Elephant


826.4
836.4
840.4
852.4
858.4
886.4
892.5
898.5
904.5
920.5
950.5
1001.5
1015.5
1029.5
1095.6
1105.6

Indian Elephant

835.4
836.4
840.5
852.4
868.4
877.4
886.4
892.5
894.5
898.5
908.5
920.5
950.5
1095.6
1105.6
1154.6
1161.6
1180.7
1183.6
1189.6
1196.6
1201.6
1211.6
1230.6
1261.6
1267.7


Rabbit

817.5
836.4
852.4
868.5
872.4
886.4
892.5
898.5
908.5
950.5
977.5
1029.5
1088.6
1095.6
1105.6
1125.5
1138.6
1161.6
1177.6
1182.6
1201.6
1221.6
1235.6
1267.7
1280.6
1311.6
1332.7
1378.5
1437.7
1453.7
1465.7
1469.7

ご覧のとおり、SpeciesID3.txt の文字 (A =、B = ) が失われています。

私はいくつかの「回避策」を試みましたが、まだ機能するものを書いていません。

どうもありがとう、

スティーブン。

4

2 に答える 2

2

サブルーチン内でスクリプト グローバルを使用し、奇妙なラベルを使用しているため、そのスクリプトを維持することを検討するかどうかはわかりません。入力レコード区切り文字$/を空の文字列に設定することにより、Perl の段落モードを使用して、検討したい方法を次に示します。

chompハッシュキーから改行を削除できないため、これは少し扱いに​​くいため、doブロックを使用して補正しました。do { ... }サブルーチンのように機能し、最後に実行されたステートメントの値を返します。この場合、配列の要素を返します。

use strict;
use warnings;
use Data::Dumper;

local $/ = "";        # paragraph mode

my %a = do { my @x = <DATA>; chomp(@x); @x; };  # read the file, remove newlines
$_ = [ split ] for values %a;                   # split numbers into arrays
print Dumper \%a;                               # print data structure

__DATA__
African Elephant


826.4
836.4
840.4
852.4
858.4
886.4
892.5
898.5
904.5
920.5
950.5
1001.5
1015.5
1029.5
1095.6
1105.6

Indian Elephant

835.4
836.4
840.5
852.4
868.4
877.4
886.4
892.5
894.5
898.5
908.5
920.5
950.5
1095.6
1105.6
1154.6
1161.6
1180.7
1183.6
1189.6
1196.6
1201.6
1211.6
1230.6
1261.6
1267.7


Rabbit

817.5
836.4
852.4
868.5
872.4
886.4
892.5
898.5
908.5
950.5
977.5
1029.5
1088.6
1095.6
1105.6
1125.5
1138.6
1161.6
1177.6
1182.6
1201.6
1221.6
1235.6
1267.7
1280.6
1311.6
1332.7
1378.5
1437.7
1453.7
1465.7
1469.7

出力:

$VAR1 = {
          'Rabbit' => [
                        '817.5',
                        '836.4',
                        '852.4',
                        '868.5',
                        '872.4',
                        '886.4',
                        '892.5',
                        '898.5',
                        '908.5',
                        '950.5',
                        '977.5',
                        '1029.5',
                        '1088.6',
                        '1095.6',
                        '1105.6',
                        '1125.5',
                        '1138.6',
                        '1161.6',
                        '1177.6',
                        '1182.6',
                        '1201.6',
                        '1221.6',
                        '1235.6',
                        '1267.7',
                        '1280.6',
                        '1311.6',
                        '1332.7',
                        '1378.5',
                        '1437.7',
                        '1453.7',
                        '1465.7',
                        '1469.7'
                      ],
          'Indian Elephant' => [
                                 '835.4',
                                 '836.4',
                                 '840.5',
                                 '852.4',
                                 '868.4',
                                 '877.4',
                                 '886.4',
                                 '892.5',
                                 '894.5',
                                 '898.5',
                                 '908.5',
                                 '920.5',
                                 '950.5',
                                 '1095.6',
                                 '1105.6',
                                 '1154.6',
                                 '1161.6',
                                 '1180.7',
                                 '1183.6',
                                 '1189.6',
                                 '1196.6',
                                 '1201.6',
                                 '1211.6',
                                 '1230.6',
                                 '1261.6',
                                 '1267.7'
                               ],
          'African Elephant' => [
                                  '826.4',
                                  '836.4',
                                  '840.4',
                                  '852.4',
                                  '858.4',
                                  '886.4',
                                  '892.5',
                                  '898.5',
                                  '904.5',
                                  '920.5',
                                  '950.5',
                                  '1001.5',
                                  '1015.5',
                                  '1029.5',
                                  '1095.6',
                                  '1105.6'
                                ]
        };

このやや冗長な出力からわかるように、結果は動物をキーとして、数値を値として持つハッシュです。名前と数字が少なくとも 2 つの連続する改行で区切られていることに信頼でき、データ内に任意の改行がない限り、この方法でうまくいきます。

于 2013-09-04T12:47:07.550 に答える
0
if (m{^([A-Z])\s*=\s*(\d+(?:\.\d)?)(?:\s+AND\s+(\d+(?:\.\d)?))?$}) {

この行には、大文字と[A-Z]それに続く等号を検索する正規表現が含まれており、両側にオプションの空白があります\s*=\s*。基本的には、そのプレフィックスを削除して、単純に数字に一致させたいだけです(\d+(?:\.\d)?)

$1$2$3は左端の左括弧から番号が付けられているため、必要な番号が$1今入ります。(括弧?:はキャプチャではなく、カウントされません。)

%speciesまた、変数のキーが種名で、値が単純な数字のリスト (抽出された観測値) になるように、変数を変更する必要があります。

そう:

if (m{^(\d+(?:\.\d)?)$}) { 
    push ${$species{$spec}}, $1; 
}

analyzeサブルーチンも同様に調整する必要があります (レベルLTRは基本的になくなっています)。

于 2013-09-04T12:42:15.870 に答える