저는 Perl을 배우고 있지만 이 문제를 해결하는 방법을 모르겠습니다.
.txt
다음 형식의 파일이 있습니다 .
1 16.3346384
2 11.43483
3 1.19819
4 1.1113829
5 1.0953443
6 1.9458343
7 1.345645
8 1.3847385794
9 1.3534344
10 2.1117454
11 1.17465
12 1.4587485
첫 번째 열에는 줄 번호만 포함되어 있으며 여기서는 관심이 없지만 두 번째 열의 값은 관련 부분입니다.
두 번째 열에 2.00보다 작은 숫자를 가진 가장 긴 연속 행 시퀀스를 출력하고 싶습니다. 위의 예에서는 3~9행이 되며 출력은 다음과 같아야 합니다.
1.19819
1.1113829
1.0953443
1.9458343
1.345645
1.3847385794
1.3534344
답변1
펄 한 줄:
perl -ne '$n = (split)[1]; if ($n > 2) {if ($i > $max) {$longest=$cur; $cur=""; $max=$i}; $i=0} else {$cur .= $n . "\n"; $i++} END {print $i > $max ? $cur : $longest}' < file.txt
더 나은 가독성을 위한 여러 줄:
perl -ne '
$n = (split)[1];
if ($n > 2) {
if ($i > $max) {
$longest=$cur;
$cur="";
$max=$i;
}
$i=0
} else {
$cur.= $n . "\n";
$i++
}
END {
print $i > $max ? $cur : $longest
}' < file.txt
라이너 1개 awk
:
awk '$2 > 2 { if (i > max) {res=cur; cur=""; max=i} i=0} $2 < 2 {cur = cur $2 "\n"; i++} END {if (i > max) res=cur; printf res}' file.txt
여러 줄:
awk '
$2 > 2 {
if (i > max) {
res=cur
cur=""
max=i
}
i=0
}
$2 < 2 {
cur = cur $2 "\n"
i++
}
END {
if (i > max) res=cur
printf res
}' file.txt
답변2
이것은 결코 사소한 일이 아닙니다. 완성된 프로그램을 제공하는 것이 다른 사람들이 프로그래밍 언어의 문제 해결 방법을 배우는 데 도움이 되는지에 대한 논쟁도 있지만, 나는 그것이 장점이 있다고 믿기 때문에 다음 프로그램을 제안합니다(이름 findlongestsequence.pl
:
#!/usr/bin/perl
use strict;
use Getopt::Long;
my $limit; my $infile;
GetOptions( 'limit=f' => \$limit, 'infile=s' => \$infile );
my $lineno=0; my $groupstart;
my $currlength=0; my $maxlength=0; my $ingroup=0;
my @columns; my @groupbuf; my @longestgroup;
if (! open(fileinput, '<', "$infile" )) {exit 1;};
while (<fileinput>)
{
$lineno++;
@columns = split(/\s+/,$_);
if ( $ingroup == 0 && $columns[1]<$limit )
{
$ingroup=1;
$groupstart=$lineno;
@groupbuf=();
}
if ( $ingroup == 1 )
{
if ($columns[1]>=$limit )
{
$ingroup=0;
$currlength=$lineno-$groupstart;
if ( $currlength>$maxlength )
{
$maxlength=$currlength;
@longestgroup=@groupbuf;
}
}
else
{
push(@groupbuf,$columns[1]);
}
}
}
close(fileinput);
if ( $ingroup == 1 )
{
$currlength=$groupstart-$lineno;
if ( $currlength>$maxlength )
{
$maxlength=$currlength;
@longestgroup=@groupbuf;
}
}
print join("\n",@longestgroup),"\n";
exit 0;
이 프로그램을 호출할 수 있습니다.
./findlongestsequence.pl --infile input.txt --limit 2.0
먼저 해석된 명령줄 인수를 사용합니다 Getopt::Long
.
그런 다음 파일을 열고 한 줄씩 읽습니다 $lineno
. 각 줄은 공백이 있는 열로 분할됩니다.
$limit
프로그램이 값이 < ( 0) 인 행 그룹에 없지만$ingroup
적절한 행을 발견하면 현재 해당 그룹($ingroup
1로 설정)에 있음을 기록하고 그룹 시작$groupstart
및 시작 버퍼링 열을 저장합니다. 2개의 배열 값입니다@groupbuf
.- 프로그램이 그러한 그룹 내에 있지만 현재 값이 보다 큰 경우
$limit
그룹 꼬리를 식별하고 길이를 계산합니다. 이전에 기록된 가장 긴 그룹보다 긴 경우 새로운 가장 긴 그룹의 내용(@groupbuf
)과 길이( )가 각각 및 에 복사됩니다 .$currlength
@longestgroup
$maxlength
그룹은 > 값이 있는 줄이 아닌 파일 끝에서 종료될 수 있으므로 이 검사는 파일 끝에서 true인 경우 $limit
에도 수행됩니다 .$ingroup
마지막으로 @longestgroup
인쇄된 내용은 \n
토큰 구분 기호 역할을 합니다.
답변3
awk를 사용하십시오.
$ cat tst.awk
$2 >= 2 {
max = getMax(cur,max)
cur = ""
next
}
{ cur = cur $2 ORS }
END {
printf "%s", getMax(cur,max)
}
function getMax(a,b) {
return ( gsub(ORS,"&",a) > gsub(ORS,"&",b) ? a : b )
}
$ awk -f tst.awk file
1.19819
1.1113829
1.0953443
1.9458343
1.345645
1.3847385794
1.3534344
답변4
<>
읽기 입력 및 트리거 연산자를 위한 관용적인 솔루션입니다.
#!/usr/bin/env perl
use strict;
use warnings;
# https://unix.stackexchange.com/questions/766081/how-to-print-the-longest-sequence-of-lines-featuring-numbers-smaller-than-a-thre
my $threshold = 2.00;
my ($section, $maxsection, $len, $maxlen);
my $flipflop;
while (<>) {
# Remove leading line number
s/^(\d+)\s+//;
# Flip flop operator
# https://www.effectiveperlprogramming.com/2010/11/make-exclusive-flip-flop-operators/
if ($flipflop = $_ <= $threshold .. $_ > $threshold) {
if ($flipflop =~ /E0$/) {
# End of section
if (!defined($maxlen) || $len > $maxlen) {
$maxsection = $section;
$maxlen = $len;
}
$len = 0;
$section = "";
} else {
$len++;
$section .= $_;
}
}
}
# One last possible end of section
if ($flipflop && $len > $maxlen) {
$maxsection = $section;
}
print $maxsection;