· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
Perl Commandline CookBook

Perl Commandline CookBook

Perl은 많은 분야에서 강력한 힘을 가지고 있지만 쉘 커맨드 라인에서 기존의 awk와 sed등을 대체하고 그이상의 많은 일을 해낼 수 있는 강력한 도구입니다. 커맨드라인 펄은 "아는만큼 쓰면된다"는 펄의 장점을 보여주는 가장 좋은 예입니다.

커맨드 라인에서 쓸수 있는 다양한 Perl 팁을 모아봅시다. Perl외의 다양한 방법들도 함께 모아서 비교해보는 것도 좋겠죠?

바로 복사해서 쓸 수 있는 CookBook을 만드는 것이 목적인만큼 팁들을 문서의 앞으로 돌리고 문서의 뒤쪽에 커맨드라인 옵션이나 유용한 문법에 대해 추가하겠습니다. -- pung96 2007-01-31 23:30:27

1.1. Perl Commandline 예제들

1.1.1. 많은 파일들을 한번에 삭제하기

find -name "*.log" -print | perl -nle unlink
find -name "*.log" -exec rm \{\} \;
find -name "*.log" -print | xargs rm
-exec를 이용한 방법이 간단하기는 하지만 계속 새로운 프로세서를 띄어야 하기 때문에 perl을 이용하는 방법이 훨씬 빠릅니다. xargs 역시 받을 있는 인자의 개수가 한계가 있기 때문에 여러번의 프로세스를 띄어야 할 것으로 예상됩니다. perl은 인자로 받는것이 아니기 때문에 하나의 프로세스로 모두 해결할 수 있습니다.

1000개 지운후에 5초 쉬도록 할 경우
find -name "*.log" -print | perl -nle 'unlink; $.%1000==0 and sleep(10);'
  • $.은 현재의 라인번호 변수입니다.

1.1.2. 여러줄의 데이터를 grep하기

perl -0777ne '/(START_FLAG.*?END_FLAG)/s and print $1' list.txt  # 파일이 작을때
perl -ne '/START_FLAG/ ... /END_FLAG/ and print;'               # 파일이 클때

1.1.3. 리스트 비교 : 복잡한 comm 구현하기

기본 아이디어는 여러 파일을 읽어서 각 라인의 적당한 패턴 혹은 전체 라인을 해쉬 키로 만들고 라인을 해쉬 값으로 만들어서 각각 파일에 대응되는 해쉬에 저장한 후에 키가 각 해쉬에 존재하는지 확인하여 출력합니다. 편의상 스크립트에서 주로 사용하지 않는 심볼릭 레퍼런스를 사용했습니다.
  • 기본 리스트비교(comm)
comm, grep 등을 이용한 쉬운 방법들이 많기는 하지만 패턴매치를 이용한 비교를 더 쉽게 이해하기 위해서 적어보았습니다. 게다가 제 경험상으로는 perl의 comm이나 grep보다 빨랐습니다(아마 메모리는 더 많이 사용할 것입니다.).
# list1 과 list2 모두에 있는 항목
grep -f list2 list1
perl -e '@a{@ARGV}=q(A..Z);while(<>){$a{$ARGV}->{$_}++};for(keys %A){print $_ if $B{$_}}' list1 list2
perl -ne 'BEGIN{@a{@ARGV}=(A..Z)}{$a{$ARGV}->{$_}++}END{for(keys %A){print $_ if $B{$_} } }' ls.log ls.log2

# list1 에만 있는 항목
grep -vf list2 list1
perl -e '@a{@ARGV}=(A..Z);while(<>){$a{$ARGV}->{$_}++};for(keys %A){print $_ unless $B{$_}}' list1 list2

# list1 + list2
cat list1 list2 | uniq
perl -e 'while(<>){$A{$_}++};for(keys %A){print $_;};'

# 속도는 좀 느리지만 간단한 방법
perl -e '@s{`cat OLD`}=( ); exists $s{$_} && print for `cat NEW`'
  1. $a{@ARGV}=(A..Z) : 인자들로 %A해쉬를 채웁니다. $a{첫번째인자}="A", $a{두번째인자}="B" 로 Z까지 채울 수 있습니다.
  2. $a{$ARGV}->{$_}++ : <>나 -n옵션으로 파일을 읽을때 현재 읽고있는 파일의 이름이 $ARGV로 할당됩니다. 이때 $a{$ARGV}는 위에서 할당한 것처럼 인자순서대로 A~Z값을 가지고 이 값을 심볼릭 레퍼런스로 이용하여 결국에는 첫번째 파일의 경우 %A에 두번째 파일은 %B를 사용합니다. 따라서 첫번째 파일의 경우 이 코드는 %A{$_}++ 로 해석됩니다. $_는 현재 라인 전체를 의미하므로 라인을 키로하고 값은 편의상 1을 더하는 방법을 씁니다.
  3. 파일을 모두 읽어서 각 해쉬를 채운후 %A의 키들을 읽어서 각 키에대해 %B에도 값이 존재하는 키들을 출력하면 %A와 %B의 키 교집합을 구할 수 있습니다.

  • 패턴 매칭을 이용한 비교
    pattern이 list1 과 list2에 모두 매치되는 항목의 list1 항목. 말이 좀 복잡하네요.
    perl -e '@A{@ARGV}=qw(L R);while(<>){/(pattern)/ and $A{$ARGV}->{$1}=$_};for(keys %L){print $L{$_} if $R{$_};}' list1 list2
    


    • 3중비교
      perl -e '@a{@ARGV}=(A..Z);while(<>){/(pattern)/ and $a{$ARGV}->{$1}=$_};for(keys %A){print $A{$_} if $B{$_}&&$C{$_} }' list1 list2
      

    1.1.4. 엑셀처럼 컬럼 계산하기

    cat data.txt | perl -ane '{$avr=$F[2]+$F[3];$sum+=$avr;print "Avr is $avr\n";}END{print "Sum is $sum\n";}' 
    
    cat data.txt | awk '{avr=$1+$2;sum+=avr;print "Avr is "avr;}END{print "Sum is "sum;}'
    
    perl -nle '{/(pattern1).*(pattern2)/ and $avr=$1+$2 and $sum+=$avr and print "Avr is $avr"}END{print "Sum is $sum";}' data.txt
    

    1.1.5. 파일 수정하기

    • oldpattern을 newstring로 수정하고 기존의 파일은 *.bak로 백업합니다.
      perl -ibak -pe 's/oldpattern/newstring/g;'
      

    1.1.6. 각 라인의 패턴에 따라 다른 파일(pattern.txt)로 분류하기

    perl -ne '{/(pattern)/ and $H{$1}.=$_;}END{for(keys %H){open F,">$_.txt";print F $H{$_};close F;}' data.txt
    
    • 파일 전체를 해쉬에 넣는 방법이므로 파일이 커지면 메모리를 많이 사용한다는 점에 유의해야 합니다. (요즘은 메모리가 커서 수백메가바이트의 파일도 처리할 수 있죠)

    1.1.7. 서브디렉토리 grep하기

    grep -r pung96 *
    에 대응되는 표현
    find | perl -nle '$f=$_;-T $f or next;open(F,$f);while(<F>){/pung96/ and print "$f : $_";}'
    

    1.2. Perl Commandline Option


    ID
    Password
    Join
    True happiness will be found only in true love.


    sponsored by andamiro
    sponsored by cdnetworks
    sponsored by HP

    Valid XHTML 1.0! Valid CSS! powered by MoniWiki
    last modified 2007-09-06 09:13:11
    Processing time 0.0104 sec