2011-04-22 21 views
1

テキストファイルを修正するには、特定のキーに基づいて各行をソートし、古いファイルをバックアップとして保存します。キーは、各行に含まれる数字です。perl in-placeテキストファイルのソート行

これを行うための簡単なスクリプトはありますか?

ありがとうございます!

+0

これをインプレースで行うのは非常に非効率的なようです。並べ替えには並べ替えが必要で、その場で行うということはファイルの内容全体を繰り返し移動することを意味します。なぜあなたはそれが記憶ではなく現場で行われることを求めていますか?良い答えが必要な場合は、特定の「解決策」で手を結びつけるのではなく、ニーズを述べる必要があります。 – ikegami

+2

'ソート'プログラムを試しましたか? 'sort'は通常、すべてのnixプラットフォームで利用可能です。 – ewh

+0

'sort'ユーティリティは、必要に応じて、インプレースではなく、一時ファイルを使用してメモリ内で動作します。それは間違いなく、偉大で効率的なツールです。 – ikegami

答えて

0

あなたが示唆していることは、実際にはかなり複雑で非効率的なので、これを行う簡単なスクリプトはありません。ファイル内の行の長さがまったく同じでない限り、ほとんど不可能(または、信じられないほどばかげている)です。

メモリで絶対に実行できず、コードを自分で書きたい場合は、おそらくdisk based merge sortです。テープドライブでどのように行うのかの例は、いくつかのガイダンスを提供します。

1

HeapsortなどのO(n log n)複雑なインプレースソートアルゴリズムがありますが、Unix sortコマンドのような簡単なものではなく、その理由を使用する理由がわかりません。あなたが厳しいパフォーマンス要件や巨大なデータセットを持っていない限り...しかし、perlとpythonはおそらく仕事のための最良のツールではありません。

1

ソートキーは、次の例のように、各行の先頭に数字のランであるとします。

5 Fine 
2 Good 
1 Every 
4 Does 
3 Boy

コマンドラインで指定された1つ以上のファイルを並べ替えるには、以下のコードを使用します。

#! /usr/bin/env perl 

use strict; 
use warnings; 

die "Usage: $0 file ..\n" unless @ARGV; 

$^I = ".bak"; 
undef $/; 

while (<>) { 
    print map $_->[0], 
     sort { $a->[1] <=> $b->[1] } 
     map { [ $_, /^(\d+)/ ? $1 : -1 ] } 
     /^(.*\n?)/mg; 
} 

@ARGVには、コマンドラインからの引数が含まれています。引数を指定しないでプログラムを実行すると、標準エラーに関する使用ガイドが生成されます。

$^I

はあなたにも perlrun documentationで取り上げPerlの -iスイッチで有効にすることができますインプレース編集用のバックアップを作成するときに、ファイル名に追加拡張子を保持しています。

-i [拡張機能]
<>構築物により処理されたファイルは、その場で編集することを指定します。これは、入力ファイルの名前を変更し、元の名前で出力ファイルを開き、出力ファイルをprintステートメントのデフォルトとして選択することで行います。

$/は入力レコードセパレータです。定義されていない値に設定すると、readline operatorへのその後の呼び出しでファイルの終わりを読み取ることを意味します。非常に大きなインプットではパフォーマンスが低下します。

whileループの各繰り返しで、特殊変数$_は、現在のファイルの内容全体を保持します。行をソートするには、最初に行を分割します。

ループ内のprintによって威嚇されることはありません。 less-than-rave reviewsにデビューしたにもかかわらず、Perlの共通のテクニックであるSchwartzian Transformです。何が起きているのかを理解するには、最後から最後まで読んでください。

  1. 現在のファイルのすべての行のリストをキャプチャします。/m regexスイッチは、^を、ターゲット文字列の先頭だけでなく、行頭でも一致させます。
  2. 各行について、その行の先頭に1つ以上の桁をキャプチャするか、デフォルトで-1にします。
  3. ソートキーの昇順で行を並べ替えます。
  4. 最後に、行をソート順に印刷します。インプレイス編集を有効にすると、printがソートされている現在のファイルに出力されます。以上の手続きスタイルで

、あなたは変換シュワルツで何が起こっているのかを理解すれば、すべての一時は、過度の混乱のように見える

while (<>) { 
    my @lines = /^(.*\n?)/mg; 
    my @augmented = map { [ $_, /^(\d+)/ ? $1 : -1 ] } @lines; 
    my @sorted = sort { $a->[1] <=> $b->[1] } @augmented; 
    print map $_->[0], @sorted; 
} 

としてループを記述します。