输出文件名中编号最高的行

输出文件名中编号最高的行

我有一个文件列表,其模式.*_[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

相关内容