.*_[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