1

ファイルAからデータを抽出し、指定された開始点と終了点を持つ列データのみをファイルBに貼り付けるコードを作成しようとしています。これまでのところ、AからBにすべてのデータを正常にコピーすることしかできませんが、そうではありません列をフィルタリングしてどこにでも行きます。splice と grep を調べてみましたが、役に立ちませんでした。Perl の経験はありません。データには列ヘッダーがありません。サンプル: データは実際には数千行の長さです - 関数にデータを挿入できません

1. AAA 565 u8y 221
2. ABC 454 9u8 352
3. ADH 115 i98 544
4. AKS 352 87y 454
5. GJS 154 i9k 141

3 番目の列 (開始:8、長さ:3) のすべての一意の値をファイル B にコピーする必要があります。Perlで特定の列のデータを抽出する方法で提供されているソリューションを試しました。無駄に。

ヒントや支援をありがとう!

 #!/usr/bin/perl
use strict;
use warnings;

#use Cwd qw(abs_path);

#my $dir = '/home/
#$dir = abd_path($dir);
my $filename = "filea.txt";
my $newfilename = "fileb.txt"; 

#Open file to read raw data
open (DATA1, "<$filename") or die "Couldn't open $filename: $!";

#Open new file to copy desired columns
open (DATA2, ">$newfilename") or die "Couldn't open $newfilename: $!";

#Copy data from original to new file

while (<DATA1>) {
    #DATA2=splice(DATA1, 0,5);
    print DATA2 $_;
    my @fifth_column = map{(split)[1]} split /\n/, $newfilename;    
}
4

3 に答える 3

3

私があなたを正しく理解していれば、これにはかなり単純なスクリプトを使用できます。

use strict;
use warnings;

my %seen;
while (<DATA>) {
    my $str = substr($_, 8, 3);   # the string you seek
    unless ($seen{$str}++) {      # if it is not seen before
        print "$str\n";           # ...print it
    }
}

__DATA__
AAA 565 u8y 221
AAA 565 u8y 221
ABC 454 9u8 352
ADH 115 i98 544
AKS 352 87y 454
GJS 154 i9k 141

出力:

u8y
9u8
i98
87y
i9k

ここDATAでは、デモ用にファイル ハンドルを使用します。また、データに重複を追加して、重複排除を示しました。に変更<DATA>すると<>、次のようにスクリプトを使用できます。

perl script.pl filea.txt > fileb.txt

これは、データが固定幅であることに依存していることに注意してください。つまり、フィールドが整列していない場合、出力が破損します。

また、これは次のような単純なワンライナーの完全なバージョンにすぎないことに注意してください。

perl -nlwe '$x=substr($_,8,3); print $x unless $seen{$x}++' filea.txt > fileb.txt
于 2013-02-26T16:53:16.997 に答える
1

次の Perl コマンドを見てください。

  • split: これにより、データ行を配列に分割できます。

例:

while ( my $line = <$input_fh> ) {
    my @items = split /\s+/, $line;   #Columns are separated by spaces or tabs
    my $third_column = $items[2];  #The column you want;
    blah...blah...blah;
}
  • substr: これにより、列情報の部分文字列を指定できます。列がタブで区切られている場合、これはあまり役に立ちません。ほとんどの非 Perl 開発者にとって、これは最初に試す方法です。ただし、使用をお勧めしsplitます。

データが一意であることを確認するための Perl のトリックがあります。ハッシュを使用して情報を保存します。ハッシュ内のデータの検索は迅速であり、exists既にそのデータを見たことがある場合は、関数を使用してすばやく検索できます。これと組み合わせるsplit

use strict;
use warnings;
use autodie;

use constants {
    INPUT_FILE  => "filea.txt",
    OUTPUT_FILE => "fileb.txt",
};

open my $input_fh, "<", INPUT_FILE;
open my $output_fh ">", OUTPUT_FILE;

my %unique_columns;
while ( my $line = <$input_fh> ) {
    my @items = split /\s+/, $line;   #Columns are separated by spaces or tabs
    my $third_column = $items[2];  #The column you want;
    if ( not exists $unique_columns{$third_column} ) {
        $unique_columns{$third_column} = 1;
        print {$output_fh} "$third_column\n";
    }
}
close $output_fh;

ハッシュは%unique_columns、ファイルの 3 列目にそのデータが以前にあったかどうかを追跡します。個々のキーを何に等しく設定してもかまいません。ただし、ゼロ以外または空白の値に設定することをお勧めします。

if ( $unique_columns{$data} )

それ以外の

if ( exists $unique_columns{$data} )

の値がゼロまたは空白でない限り、プログラムは引き続き機能します$unique_columns{$data}が、それ以外の場合は失敗します。

于 2013-02-26T17:47:32.693 に答える
0

固定長に関しては、パック/アンパックに勝るものはありません。このチュートリアルを学ぶと、あなたの生活が楽になり、この仕事が簡単になります。

http://linux.die.net/man/1/perlpacktut

于 2013-02-26T20:29:16.580 に答える