3

次のようなファイルがあります。

text text text text : 6 min
text text text text : 2 min
text text text text : 8 min
text text text text : 2 min

その出力を取得するには、このファイルをソートする必要があります。

text text text text : 2 min
text text text text : 2 min
text text text text : 6 min
text text text text : 8 min

私はこれをやろうとしましたが、うまくいきません:

my @copy = ();
open (INFILE, $ARGV[0]);
while (<INFILE>) {
push (@copy, $_);
}
my @lines = sort grep /^: (\d+) min/ , @copy;
print @lines;

perl でこれを行う簡単な方法はありますか?

4

6 に答える 6

8

それはより簡単ですsort

$ sort -t: -k2 file
text text text text : 2 min
text text text text : 2 min
text text text text : 6 min
text text text text : 8 min
  • -t:「列の区切り文字を : に設定する」ことを意味します。
  • -k2は「2 列目のフィルター」、つまり . の直後を意味し:ます。
于 2013-06-24T08:35:31.813 に答える
5

sort最も単純に見えるため、最初に投稿されたソリューションをお勧めします。ただし、これは perl バージョンです。これは、シュワルツ変換に基づいています。これは必須ではありませんが、より大きなファイルの場合はおそらく効率的であり、見た目もすっきりします。

use strict;
use warnings;

my @lines = <>;    # read the input file
@lines = map $_->[1],
         sort { $a->[0] <=> $b->[0] }
         map { my ($num) = /:\s*(\d+)/; [ $num, $_ ] } @lines;
print @lines;

基本的な考え方は次のとおりです。

  • 数値を抽出するステートメントから開始し、mapその数値を含む 2 要素配列への参照を返し、元の行[ $num, $_ ]
  • 最初の要素に基づいて、結果のリストを並べ替えます。
  • map配列を元の行に戻す別のステートメントで終了します。
于 2013-06-24T08:47:05.907 に答える
1

それが perl でなければならない場合 (fedorquis の提案は非常に良いです)、このナゲットでそれを行う必要があります。

my @file=<>;
foreach (sort {(split(' ',$a))[5] <=> (split(' ',$b))[5]} @file) {print;}

ファイル名をパラメーターとして指定します。

于 2013-06-24T08:42:56.413 に答える
1

あなたの正規表現は間違っています。あなたがしたい:

/[^:]+: (\d+) min/

また、これだけはできませんか?

@copy = <INFILE>;
于 2013-06-24T08:37:25.570 に答える
0

シュワルツ変換を使用して、次のような数値に基づいて行を並べ替えることができます

use strict;
use Data::Dumper;

my @lines = ("Test:2 min","Test:8 min","Test:6 min");
print Dumper(\@lines);

@lines = map { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map { [$_, /(\d+) min/] } @lines;

@lines = sort @lines;
print Dumper(\@lines);

出力:

$VAR1 = [
          'Test:2 min',
          'Test:8 min',
          'Test:6 min'
        ];
$VAR1 = [
          'Test:2 min',
          'Test:6 min',
          'Test:8 min'
        ];
于 2013-06-24T08:47:29.133 に答える
0

my @lines = map { $_->[1] } sort { $a->[0] <=> $b->[0]} map { [ /:\s(\d+)/, $_ ] } @copy

使い方

右から順に、最初のマップは配列の配列を作成します。各配列要素には、最初の要素として各行から抽出された数値が含まれ、2 番目の要素として行全体が含まれます。

次に、数値比較のために、いわゆる ufo 演算子を使用して設定したばかりの配列の最初の要素に対してソートが行われます。

最後に、最後のマップは 2 番目の要素のみを正しい順序で抽出します

この方法は「Schwartzian Transform」として知られており、perldoc perlfaq4 セクション「How do I sort an array by (anything)?」にあります。

于 2013-06-24T08:48:03.823 に答える