2

複数のファイルのすべての行の 2 番目のフィールドが必要です。一部の行の先頭にスペースがあるため、「カット」は機能しません。

perl -anle 'print $F[1]' *manyfiles* > result 

動作しますが、遅いです。

これを行うための大幅に高速な方法はありますか?

4

8 に答える 8

3
awk '{print $2}' files ... > result

より速いかもしれません。

于 2012-04-07T17:20:00.263 に答える
2

カットスクリプトを使用する前に、先頭のスペースを sed で削除できませんでしたか?

たとえば sed -e 's/^[ \t]*//'、先頭にスペースがないファイルでストリームを生成します。これをスクリプトにパイプするだけです。

于 2012-04-07T17:22:02.913 に答える
1
sed -rn 's/\s*[^\s]+\s+([^\s]+).*/\1/p' file1 file2 > parsed_text

より速くする必要があります。

または、これを使用してファイルのリストを作成できます。

find /path/to/files/ -type f -iname "*" -print0 | xargs -0 -I {} sed … 

(たとえば、マスクの「iname」は、使用しない場合はより高速になります)

于 2012-04-07T22:10:04.757 に答える
1

Parallel :: ForkManagerは、特に出力をソースファイルごとにグループ化する必要がない場合に役立つことがあります。ただし、ディスクに同時にアクセスするプロセスの数を増やすと、速度が低下する可能性もありますが、一見の価値があります。

次の例は、Parallel::ForkManagerマニュアルページから採用されています(以前のバージョンに存在する明らかなエラーは修正されています)。

#!/usr/bin/env perl

use strict; use warnings;

use Parallel::ForkManager;

my ($maxproc) = @ARGV;
my @files = ('01' .. '10');

my $pm = Parallel::ForkManager->new($maxproc);

for my $file (@files) {
    my $pid = $pm->start and next;
    my $ret = open my $h, '<', $file;

    unless ($ret) {
        warn "Cannot open '$file': $!";
        $pm->finish;
    }

    while (my $line = <$h>) {
        next unless $line =~ /^\s*\S+\s+(\S+)/;
        print "$1\n";
    }

    $pm->finish;
}

$pm->wait_all_children;

上記のスクリプトを、それぞれ1_000_000行の10個のファイルで実行しました。各ファイルでは、行の20%に先頭の空白があります。Parallel :: ForkManagerは、一見IOバウンドのタスクを高速化できますか?を参照してください。詳細については。

#同期
#echo 3> / proc / sys / vm / drop_caches
$ / usr / bin / time -f'%Uuser%Ssystem%Eelapsed%PCPU'./process.pl1>出力
24.44user 0.93system 0:29.08経過87%CPU

$rm出力
#同期
#echo 3> / proc / sys / vm / drop_caches
$ / usr / bin / time -f'%Uuser%Ssystem%Eelapsed%PCPU'./process.pl2>出力
24.95user 0.91system 0:18.31経過141%CPU

$rm出力
#同期
#echo 3> / proc / sys / vm / drop_caches
$ / usr / bin / time -f'%Uuser%Ssystem%Eelapsed%PCPU'./process.pl4>出力
24.70user 0.88system 0:17.45経過146%CPU

$rm出力
#同期
#echo 3> / proc / sys / vm / drop_caches
$ / usr / bin / time -f'%Uuser%Ssystem%Eelapsed%PCPU'./process.pl1>出力
25.31user 0.95system 0:29.72経過88%CPU

ですから、すべてのコアを利用することで、いくらかの利益があるように思えます。

私は、Perl + Parallel::ForkManagerの使用がそれらのいずれよりも優れているかどうかを確認するために与えられた他の提案のいずれも試しませんでした。

この方法の明らかな欠点の1つは、ソースファイルからの行をインターリーブすることです。これは、特定の状況では問題になる場合と問題にならない場合があります。

于 2012-04-07T18:35:44.220 に答える
0

これらのソリューションにいくつかの数字を入れたかったのです。aaqp.txtファイルは 130 MB で、1,000,000 行あり、1 行あたり平均 7 フィールドです。このために実際に 50 GB 以上のサンプル データを生成しましたが、これらのいずれかが完了するのを待つのが待ちきれませんでした。

$ time perl -anle 'print $F[1]' aaqg.txt > result

real    0m18.526s
user    0m18.368s
sys     0m0.089s

$ time awk '{print $2}' aaqg.txt  > result

real    0m4.051s
user    0m3.592s
sys     0m0.091s

$ time perl -nE 'say $1 if m/\s*\S+\s+(\S+)/' aaqg.txt > result

real    0m2.009s
user    0m1.901s
sys     0m0.066s

$ time perl -nE'say /^\s*\S+\s+(\S+)/' aaqg.txt > result

real    0m2.069s
user    0m1.813s
sys     0m0.069s
于 2012-04-11T12:13:10.160 に答える
0

パール:

perl -ne 'print "$1\n" if m/\s*\S+\s+(\S+)/' manyfiles >result

非 Perl:

awk '{print $2}' manyfiles >result
于 2012-04-07T18:22:08.073 に答える
0

以下が不十分な場合は、

perl -nE'say /^\s*\S+\s+(\S+)/' *

やってみます

perl -ple's/^\s+//' * | cut

これが 1 回限りのことではなく、速度が本当に重要な場合は、C で小さなトリミング ツールを記述してperl、上記を置き換えることができます。

于 2012-04-07T21:05:41.527 に答える