.*_[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 해킹은 각 입력 줄에서 파일 이름 접두사와 번호를 분리하고 이를 사용하여 두 개의 해시 배열을 구축합니다. 즉, %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