我有一个文件列表,其模式.*_[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 hack splits 从每个输入行中提取文件名前缀和数字,并使用它们构建两个哈希数组 -%n
保存每个文件名前缀的最大数字,并%f
保存关联的文件名。两个哈希值使用相同的密钥(前缀)。
它将 之前的所有内容捕获_
为“前缀”,并将 之后的所有数字_
(直到行尾或第一个非数字字符)捕获为数字。
与正则表达式模式不匹配的行将^(.*)_(\d+).*$
被完全忽略。如果需要,您可以在发生这种情况时打印一条警告消息(留给读者作为练习)。
一旦读取输入,它就会迭代%f
哈希值之一的键并打印文件名。
这是与独立 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