주어진 문제
다음과 같이 탭으로 구분되고 큰따옴표로 둘러싸인 컬럼들이 있다. 이 중에서 CONTACTME가 1인 줄만 뽑아서 SKUTITLE을 기준으로 정렬해서 출력하라. 각 컬럼값 자체에는 큰따옴표가 없다고 가정한다.
"EMAIL" "CONTACTME" "SKUTITLE" "foo2@bar.com" "1" "Product3" "foo@bar.com" "0" "Product1" "foo1@bar.com" "1" "Product2"
다양한 Perl 코드
원저자의 코드는 좀 장황하다.
#!/usr/bin/perl -w
use strict;
my @records = ();
foreach my $line ( <> )
{
my @record = map {s/"//g; $_} split("\t", $line);
push(@records, \@record);
}
my $EMAIL = 0;
my $CONTACTME = 1;
my $SKUTITLE = 2;
my @contactRecords = ();
foreach my $r ( @records )
{
push(@contactRecords, [$$r[$SKUTITLE], $$r[$CONTACTME], $$r[$EMAIL]]);
}
@contactRecords = sort {$$a[0] cmp $$b[0]} @contactRecords;
@contactRecords = grep($$_[1] eq "1", @contactRecords);
foreach my $r ( @contactRecords )
{
print join("\t", @$r), "\n";
}
나도 한번 만들어 봤다.
#!/usr/bin/perl
use constant EMAIL => 0;
use constant CONTACTME => 1;
use constant SKUTITLE => 2;
my @dat;
while(<>){
s/"//g;
@_ = split /[\t\r\n]/;
next unless($_[CONTACTME] eq "1");
push @dat, "$_[SKUTITLE]\t$_[CONTACTME]\t$_[EMAIL]\n";
}
print sort @dat;
음.. 조금 더 내려가니 괜찮은 작품들이 보이기 시작한다.
#!/usr/bin/perl
use strict;
use warnings;
my @records;
push @records, [ (/"(.*?)"/g)[0,1,2] ] while <>;
($\,$,)=("\n","\t");
print "@$_" for
sort { $a->[0] cmp $b->[0] }
grep $_->[1] eq '1', @records;
앗! 정신이 혼미해지는걸...
#!/usr/bin/perl
my @recs = sort { $a->[0] cmp $b->[0] } grep { $_->[1] eq '1' }
map { my @r = split /\t/; [map { s/"//g; $_ } @r[2, 1, 0]] } <>;
print join("\t", @$_), "\n" for @recs;
안 돌아가길래 조금 손 봤지만 이것도 비슷하다.
#!/usr/bin/perl
($,, $\) = ("\t", "\n");
print @$_ foreach
sort { $a->[0] cmp $b->[0] }
grep { $_->[1] eq "1" }
map { [@$_[2,1,0]] }
map { s/"//g for @$_; [@$_] }
map { [split /[\t\r\n]/] }
<>;
그래서 나의 결론은 버킹검이다.
#!/usr/bin/perl
print join("\t", @$_), "\n" for
sort { $a->[0] cmp $b->[0] }
grep { $_->[1] eq '1' }
map { [@$_[2,1,0]] }
map { s/"//g for @$_; [@$_] }
map { [split /[\t\r\n]/] }
<>;
한줄로 끝내기!
perl -e 'print join("\t", @$_), "\n" for sort { $a->[0] cmp $b->[0] } grep { $_->[1] eq '1' } map { [@$_[2,1,0]] } map { s/"//g for @$_; [@$_] } map { [split /[\t\r\n]/] } <>' < data.txt
이걸 단번에 한줄로 코딩하면 인간일까?
멋져요!! 이래서 펄이 좋았는데. 2단계부터는 잘 모르겠네요 ㅋ -- bs
펄의 최소한의 기능(도구)들을 모아서 만드는 장인의 역량에 따라 조합해서 쓴다는 정신은 참 맘에 드네요 ;> --firefly
저도 한참을 뜯어보고 이해했습니다. 한 수 배웠죠. 확실히 언어학을 전공한 사람이 만든 언어라 오묘합니다. 그러고 보면 언어학 전공해 놓고 프로그래밍언어를 만드는 것도 참 대단해요. 인문학과 컴퓨터과학을 넘나들다니... -- Huidae Cho
꼭 펄로 해야 하나요? sed s/\"//g t | awk '{if($2==1) print $3" "$2" "$1}' | sort
Perl의 아름다움에 빠지려면 당연히 Perl로 해야죠. 그건 shell의 아름다움이라고 하죠. ;)
sed 's/"\([^"]*\)" "\([^"]*\)" "\([^"]*\)"/\3 \2 \1/; / 0 /d' data.txt | sort
GNU sed*만* 이용하면 -.-;; 이건 GNU sed의 아름다움이 되겠군요.
gsed -n 's/"\([^"]*\)"\t"\([^"]*\)"\t"\([^"]*\)"/\3"\2"\1/
/"0"/d
################################################################################
# GNU sed sort by Greg Ubben http://sed.sourceforge.net/grabbag/scripts/sodelnum.sed
# Modified by Huidae Cho for GNU sed 4.0.9
H
$!b
s/.*/° !"#$%\&'"'"'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/
H
g
:sort
s/\(\n\([^°\n]*\)\([^°\n]\)[^°\n]*\)\(\n.*\)\?\(\n\2\([^°\n]\)[^°\n]*\)\(\n.*°.*\6.*\3\)/\5\1\4\7/
t sort
# end of sort
################################################################################
s/^\n\(.*\n\)°.*$/\1/
s/"/\t/g
:print
P
s/[^\n]*\n//
/./b print' data.txt
한 줄로 하자면 (-.-;;){100}
gsed -n 's/"\([^"]*\)"\t"\([^"]*\)"\t"\([^"]*\)"/\3"\2"\1/; /"0"/d; H; $!b; s/.*/° !"#$%\&'"'"'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~/; H; g; :sort; s/\(\n\([^°\n]*\)\([^°\n]\)[^°\n]*\)\(\n.*\)\?\(\n\2\([^°\n]\)[^°\n]*\)\(\n.*°.*\6.*\3\)/\5\1\4\7/; t sort; s/^\n\(.*\n\)°.*$/\1/; s/"/\t/g; :print; P; s/[^\n]*\n//; /./b print' data.txt
다시 보니 GNU sed 버전은 아름답다기보단 삽질 같군요.
그런 심오한 뜻이 있었군요.. simple is the best 간단한게 좋은것 같습니다 ㅋ