ファイル名の中で最も高い番号の行を出力します。

ファイル名の中で最も高い番号の行を出力します。

.*_[0-9]*\.txt次のパターンのファイルのリストがあります。

todo_1.txt
todo_3.txt
todo_91.txt
done_44.txt
done_12000203.txt

ファイル名の接尾辞は常に終わりますが、接頭辞はにすることが_[0-9]*.txtできます[a-zA-Z0-9.]*。最大数のファイルだけを出力したいです。

todo_91.txt
done_12000203.txt

答え1

$ perl -lne '($prefix,$num) = m/^(.*)_(\d+).*$/;
             if ($num > $n{$prefix}) { $f{$prefix} = $_; $n{$prefix} = $num };
             END { foreach (sort keys %f) { print $f{$_} } }' input.txt 
done_12000203.txt
shopping.list_292.txt
todo_91.txt

この高速で汚れたPerlハッキングは、各入力行からファイル名のプレフィックスと番号を分離し、それを使用して2つのハッシュ配列を構築します。つまり、%n各ファイル名のプレフィックスの最大数を保存し、%f関連するファイル名を保存します。両方のハッシュは同じキー(プレフィックス)を使用します。

前のすべてのコンテンツを_「プレフィックス」としてキャプチャし、その後のすべてのコンテンツ_(行の末尾または数字ではなく最初の文字まで)を数字でキャプチャします。

正規表現パターンと一致しない行は^(.*)_(\d+).*$完全に無視されます。必要に応じて、このような場合に警告メッセージを印刷できます(読者の練習問題として残す)。

入力を読み取ると、%fハッシュの1つのキーを繰り返してファイル名を印刷します。


以下は、スタンドアロンのPerlスクリプトと同じ少しクールなバージョンです:

#!/usr/bin/perl

use strict;
my (%f,%n);

while(<>) {
  s/#.*//;          # strip comments (#)
  s/^\s+|\s+$//g;   # strip leading and trailing spaces
  next if (m/^$/);  # ignore blank lines
  chomp;   # strip newline from end of line.

  my ($prefix,$num) = m/^(.*)_(\d+).*$/;

  if ($num > $n{$prefix}) {
    $f{$prefix} = $_;
    $n{$prefix} = $num;
  };
}

foreach (sort keys %f) {
  print $f{$_}, "\n";
}

たとえば、別の名前で保存してfind-largest.pl実行可能にし、chmod +x find-largest.pl次のように実行します。

$ ./find-largest.pl input.txt 
done_12000203.txt
shopping.list_292.txt
todo_91.txt

関連情報