주어진 문제
다음과 같이 탭으로 구분되고 큰따옴표로 둘러싸인 컬럼들이 있다. 이 중에서 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 간단한게 좋은것 같습니다 ㅋ