2

次のようなさまざまなデータ要素を実行して取得する Perl スクリプトを作成しています。

1253592000
1253678400                 86400                 6183.000000
1253764800                 86400                 4486.000000 
1253851200  36.000000      86400                10669.000000
1253937600  0.000000       86400                 9126.000000
1254024000  0.000000       86400                 2930.000000
1254110400  0.000000       86400                 2895.000000
1254196800  0.000000                             8828.000000

このテキスト ファイルの各行を問題なく取得できます。

これらの各フィールドを取得するために正規表現を使用しています。$line などの変数に行を追加したら、区切り文字が異なる場合でも、これらの各フィールドを取得して独自の変数に配置するにはどうすればよいですか?

4

6 に答える 6

14

この例は、区切り文字として空白を使用する ( split ) または固定列レイアウト ( unpack ) を使用して行を解析する方法を示しています。unpack大文字 (A10 など) を使用すると、空白が削除されます。: brian d foy が指摘してsplitいるように、フィールドの位置情報が失われるため、フィールドが欠落している状況 (たとえば、データの 2 行目) ではこのアプローチはうまく機能しません。unpack私たちがあなたのデータを誤解していない限り、ここに行く方法です。

use strict;
use warnings;

while (my $line = <DATA>){
    chomp $line;
    my @fields_whitespace = split m'\s+', $line;
    my @fields_fixed = unpack('a10 a10 a12 a28', $line);
}

__DATA__
1253592000                                                  
1253678400                 86400                 6183.000000
1253764800                 86400                 4486.000000
1253851200 36.000000       86400                10669.000000
1253937600  0.000000       86400                 9126.000000
1254024000  0.000000       86400                 2930.000000
1254110400  0.000000       86400                 2895.000000
1254196800  0.000000                             8828.000000
于 2009-09-29T20:31:07.417 に答える
3

私のモジュールDataExtract::FixedWidthを使用してください。これは、perl で固定幅の列を操作するための最も完全な機能を備えており、十分にテストされています。これが十分に高速でない場合は、 を渡して、unpack_stringヒューリスティックな境界検出の必要性をなくすことができます。

#!/usr/bin/env perl
use strict;
use warnings;
use DataExtract::FixedWidth;
use feature ':5.10';

my @rows = <DATA>;
my $de = DataExtract::FixedWidth->new({
  heuristic => \@rows
  , header_row => undef
});

say join ('|',  @{$de->parse($_)}) for @rows;

    --alternatively if you want header info--

my @rows = <DATA>;
my $de = DataExtract::FixedWidth->new({
  heuristic => \@rows
  , header_row => undef
  , cols => [qw/timestamp field2 period field4/]
});

use Data::Dumper;
warn Dumper $de->parse_hash($_) for @rows;

__DATA__
1253592000
1253678400                 86400                 6183.000000
1253764800                 86400                 4486.000000
1253851200  36.000000      86400                10669.000000
1253937600  0.000000       86400                 9126.000000
1254024000  0.000000       86400                 2930.000000
1254110400  0.000000       86400                 2895.000000
1254196800  0.000000                             8828.000000
于 2010-07-15T03:40:21.817 に答える
0

列名とフォーマットがよくわかりませんが、 Text::FixedWidthを使用してこのレシピを好みに合わせて調整できるはずです

use strict;
use warnings;
use Text::FixedWidth;

my $fw = Text::FixedWidth->new;
$fw->set_attributes(
    qw(
        timestamp undef  %10s
        field2    undef  %10s
        period    undef  %12s
        field4    undef  %28s
        )
);

while (<DATA>) {
    $fw->parse( string => $_ );
    print $fw->get_timestamp . "\n";
}

__DATA__
1253592000
1253678400                 86400                 6183.000000
1253764800                 86400                 4486.000000
1253851200 36.000000       86400                10669.000000
1253937600  0.000000       86400                 9126.000000
1254024000  0.000000       86400                 2930.000000
1254110400  0.000000       86400                 2895.000000
1254196800  0.000000                             8828.000000
于 2009-09-30T13:35:08.083 に答える
-1

行を分割できます。あなたの区切り文字は単なる空白のように見えますか? 次の順序で何かを行うことができます。

@line = split(" ", $line);

これにより、すべての空白が一致します。その後、境界チェックを行い、$line[0]、$line[1] などを介して各フィールドにアクセスできます。

Split は、文字列ではなく正規表現を区切り文字として使用することもできます。

@line = split(/\s+/, $line);

これは同じことをするかもしれません。

于 2009-09-29T20:08:40.703 に答える
-1

すべてのフィールドが同じ固定幅で、スペースでフォーマットされている場合は、次を使用できますsplit

@array = split / {1,N}/, $line;

Nフィールドの with はどこにありますか。これにより、空のフィールドごとにスペースが生成されます。

于 2009-09-29T20:18:29.937 に答える
-2

固定幅の区切りは、次のように行うことができます。

my @cols;
my %header;
$header{field1} = 0; // char position of first char in field
$header{field2} = 12;
$header{field3} = 15;

while(<IN>) {

   print chomp(substr $_, $header{field2}, $header{field3}); // value of field2 


}

私の Perl は非常にさびているので、そこに構文エラーがあると確信しています。しかし、それが要点です。

于 2009-09-29T20:10:33.553 に答える