Archive for the ‘Perl’ Tag

Perl 기본 문법

아래 글은 처음에 Simon Cozens의 Beginning Perl 이라는 책으로

공부를 시작하면서 나름대로 정리해놓은 것이다.

Perl은 문법이 워낙 다양한 만큼 자주 까먹어서 정리해놓고 Ctrl+F로 찾는 것이

도움이 많이 된다.

 

처음

ord(‘#’);   # returns ascii code of ‘#’

‘ adsfadfa’ # 아무것도 처리하지 않는다 /t /n 등… 하지만 //와 /. 만은 처리한다

q/ / , qq< > 등으로 바꿔서 쓸 수 있다.

print “ba”x3; # ba를 세번 출력한다

“afds”.”123″ # 문자열 합치기 연산자 (afds123 리턴)

변수:

use strict 사용을 하지 않으면

전역 멤버 변수 각각 뭐 잘 지정됨

만일 use strict 사용하면

전역은 our 멤버는 my로 명시해주어야함

기본적으로 단일 변수는 $, 배열은 @, 해쉬는 %로 시작한다. 그러나 이는 변수 형을 뜻하지 않고 리턴형을 말한다.

$name=”js”; #일때

“asf $name”; #은 asf js 를 리턴한다

스트링 변수 뒤에 바로 붙여 써야할 때는

${name}th # prints jsth

와 같이 사용

입력 받기:

$comment=<STDIN>;


3장 리스트와 해쉬

(12, 34, 1) #3개 원소를 가진 리스트이다.

qw/ / 등으로 쓸 수 있는데 원소의 구분은 comma가 아닌 공백으로 한다. qw/12 34 1/ 와 같이..

(3, 4, 5, 7) 이나 (3, (4, 5), 7) 은 서로 같다

리스트 원소의 접근은 대괄호로 한다.

@aa=(3, 4, 5, 7);

@aa[2]; #는 5를 리턴한다. 음의 인덱스는 뒤에서 부터 센다. aa[-1]은 7을 리턴한다.

@aa[(2,3)] 또는 @aa[2,3] 을 통해 부분 리스트를 구할 수 있다. 이는 (5, 7) 리스트를 리턴한다.

(1 .. 4) 는 (1, 2, 3, 4) 를 리턴한다. 정수가 아닐 때에는 버림한다. (1.3 .. 4.9) 도 준식과 같은 결과를 리턴한다.

(‘a’ .. ‘k’) 는 문자열 순서대로 리스트가 생긴다. 원소를 뒤집고 싶다면 reverse() 함수를 사용한다.

@at 과 $at 은 동시에 선언 가능하다( 각각 다른 변수이다.)

@at=(3, 4, 5);

$len=@at; # 이렇게 한 경우 $len 에는 자동으로 at의 길이인 3이 저장된다.

print @at; # 345 로 출력한다

print “@at”; # 3 4 5 로 출력한다

$a=(@at)[2]; 로 접근하면 $a에는 5가 저장된다

$a=$at[2]; 로 표현해도 같다 $ @ 기호는 본체의 타입이 아니라 리턴 값의 타입을 나타낸다.

my $ele;

for $ele (@at){ print $ele, “\t” } 하면 3    4    5 와 같이 출력된다. (모든 원소 출력)

# $ele 가 없다면 perl 이 알아서 $_ 라는 변수를 사용한다.

$#at 은 @at 리스트의 가장 높은 인덱스를 리턴한다. 즉 2 를 리턴함

리스트를 스택처럼 쓸 수 있다. pop @at 을 하면 가장 마지막 원소가 리턴되면서 리스트에서 제거된다

push @at, “asdf”; # asdf 스트링을 푸시

앞의 원소 쪽에서 push pop을 위해서는 unshift, shift 를 사용하면된다.

sort @at 을 하면 정렬된다.

해쉬:

%aa =(

amy => “good”,

bob => “good”,

chris => “bad”,

david => “nice”

);

화살표 좌측이 key값

배열과 호환이 되지만 key가 분간이 안가므로 조심해야한다

%aa=@bb;

@bb=%aa;

등의 연산이 된다는 소리다. (“amy”, “good”, “bob”, …) 과 같은 순서로 변환된다.

해쉬 접근은 $aa{david} 과 같이 한다. david는 따옴표를 붙여도 안붙여도 다 된다.


Loops and Decisions

변수 여러개 한방에 정의:

my ($a, $b); # 괄호 빼먹으면 안된다

chomp(어떤 스트링,[또 스트링]); 은 입력시에 캐리지 리턴을 하면서 생기는 개행문자를 없애준다.

사실 chomp는 우측 trim의 애칭이다.

if( not exists $aa{$i}){} # 이 것은 %aa 해쉬에 $i 이름의 key가 존재하는 않는 지를 검사한다

die “asdfafd”; # 에러 출력후 프로그램이 멈춤

defined $a # $a가 선언된 후에 초기화가 되었는지 판별한다

위의 if문은 다음과 같이 표현가능하다

die “asdfafd” exists $aa{$i};

또는

exists $aa{$i} or die “asdfafd”;

elseif 가 아니라 elsif를 사용해야 한다

중요 for문에서 $_ 는 단순 대입이 아니라 별칭이다 (C언어에서 &) 즉, $_을 변화시키면 해당 변수들이 같이 변한다.

작업 뒤에 for문을 써도 된다.

@ARGV는 실행시의 argument 배열이다.

last는 C언의 break; 이다

next는 C언어의 continue; 이다


Regular Expressions

split “asd adf”; # 띄어쓰기로 구분된 문장을 나누어진 배열로 리턴한다.

if($_ =~ /adf/) # 기본변수에 adf가 포함되어있나. if(/adf/)로 해도 됨

if($_ !~ /adf/) # 기본변수에 adf가 포함안되어있나

if(/adf/i) # insensitive matching 이다 일단 대소문자 구분은 안하는데 다른 것은 잘 모르겠다.

Perl Regex에서 특별한 기능을하는 Metacharacter는

. * ? + [ ] ( ) { } ^ $ | \   의 12개 이다.

기능을 없애고 싶다면 \Q 와 \E 의 짝으로 묶어버리면 된다.

if(/\Q$pattern\E/) 와 같이 사용하면 pattern 변수안에 들어있는 metacharacter들은 무시된다.

while(<>){} # 이 순환문은 실행시 던져진 아규먼트 이름을 가진 파일을 열어서 한 줄씩 $_로 읽어들인다

[^aeo] 는 aeo를 포함하지 않은 것

[1-3a-d] 와 같이 이어 붙이면 1-3또는 a-d라는 소리

\d 는 숫자 \w는 단어(문자또는 숫자) \s 는 공백에대한 shortcut이다. 각각 대문자로 쓰면 그것을 제외한다는 뜻이다.

\b 는 boundary로 공백이나 ” 등의 문자 또는 문자열의 시작 및 끝을 뜻한다. 즉 한 문장에서 단어단위로 자를 때 유용.

a? 라고 쓰면 a가 있을 수도 있고 없을 수도 있다는 것이다. s?he 는 she or he를 뜻한다

a+ 라고 쓰면 a가 하나 일수도 있고 연속 여러개일 수도 있다는 것이다.

a* 라고 쓰면 a가 없을 수도 있고 있을 수도 있고 여러개일 수도 있다는 것이다.

a{2,4} 라고 쓰면 a가 2번 3번 4번 반복될 수 있다는 것이다.

a{3,} 라고 쓰면 a가 3번 이상 반복될 수 있다는 것이다.

s/asdf/ase/; #처음 찾은 asdf 하나를 ase로 변환

s/asdf/ase/g; #모든곳에서 변환

유닉스 등에서 경로를 넘겨줄 때 \/usr\/bin 과 같은식으로 불편한데 s#/usr/bin/#으로 사용가능함

/m /s 등은 http://gypark.pe.kr/wiki/Perl/정규표현식#H_1_1_10 참고

/x 는 너무 드러운 정규식이 나왔을 때 공백 무시하게 하여 정리해서 볼 수 있게 해줌

split join 알아서 잘하면되고

transliteration은 substitute를 여러개 동시에 한다.

tr/asdf/0123/; 과 같이 쓰면 af는 03으로 바뀔 것이다. 여기서 질문은 $_ 이외의 다른 변수의 문자열은 어찌 바꾸냐인데?

$a =~ tr/asdf/0123/; 은 $a 내부에서 바뀐 횟수를 리턴하므로

$cnt= $a =~ tr/asdf//; 를 통해 asdf가 등장한 횟수를 셀 수 있다. 이렇게하면 아무 일도 발생하지 않지만

$a =~ tr/asdf//d; 를 쓰면 발생한 곳은 다 지워진다.

More Advanced Topic는 일단 뛰어넘기ㅋ


파일

<>는 <ARGV>의 약자

$/ 는 separator를 결정함. 기본값은 \n 임. 만일 빈 것 “”으로 지정하면 아무 공백도 없는 newline을 선택한 것(문단 단위)

undef로 지정하면 separator 없이 모든 문자를 한 변수에 대입하게됨

rand(숫자) 는 0에서 숫자 사이의 무작위 수 리턴

< $filename : 파일에서 읽어오기(STDIN 으로 입력 받는 것임)

> $filename : 원본 없애고 쓰기(위험)

>> $filename : 이어쓰기

숫자의 경우 <=> 문자의 경우 cmp 비교는 단순 == 또는 eq 와는 다르다.

왼쪽이 크면 1 같으면 0 오른쪽이 크면 -1을 리턴한다.

sort{$a <=> $b} 로 비교 방법을 지정해 줄 수 있다. $a, $b는 perldoc 검색해보니 sort에서만 쓰이는 특수변수라 한다.

handle을 대체하려고 할 때 *문자를 사용한다.

*INPUT=*STDIN 을 통해 파일 입출력을 하려고 만든 핸들을 STDIN으로 대체할 수 있다.

*을 이용하면 별칭으로 지정하는 것이다. (하나를 변경하면 다른 것도 같이 바뀐다.)

binmode FILEHANDLE; 을 사용하면 개행및 EOF 처리를 하지 않는다.(보통 문서들은 OS마다 각각 처리해준다)

만일 파일핸들을 많이 사용한다면 print FILEHANDLE “asdfa” 를 매번 써주기 귀찮으므로

select FILEHANDLE; 을 한번 써주면 그 이후의 print는 모두 STDOUT이 아닌 그 핸들로 간다.

다시 복구해주는 것을 잊으면 안된다.

localtime 함수는 로컬타임을 리턴 자세한건 perldoc 참조하면 될듯..

기본적으로 perl은 read write시에 버퍼링을 한다. 이것을 끄려면 $|=1; 로하면 되고 켜려면 0으로 하라

unix등의 시스템에서 file permission 은 umask(expr) 로 설정할 수 있다

piping: 어떤 프로그램의 출력을 다른 프로그램의 입력으로 사용 : ‘|’ 기호를 이용하면 됨

먼저오는 프로그램 | 뒤에 오는 프로그램 형식으로 됨

File test: 파일을 열기 전에 상태 테스트를 해봄 if(-d $filename) 등으로 할 수 있음 -d 대신 다른 것도 많음


References

$asdf=\@array; # 같이 사용하면 array에 대한 reference라고 할 수 있는데 여기서 단순 포인터가 아니라 별칭과 같은 개념이라서 값을 변화시키면 같이 변한다.

배열의 경우 $as=[2,3,4] 과 같이 () 대신 []로 사용하면 바로 익명reference를 생성 할 수 있다.

해쉬의 경우 $as={a=>”as”, b=>”bs”}; 와 같이 () 대신 {}로 사용하면 바로 익명 reference를 생성할 수 있다.

접근은 @{$as} 또는 %{$as} 등으로 할 수 있다.

배열의 reference의 경우 ${$as[0]} 와 같이 접근해야 할 경우가 있는데 귀찮으므로 $as->[0]으로 표기한다.


Subroutines

서브루틴은 C언어의 함수와 같은 것

sub asdf{

} 와 같이 정의하고 사용하면 된다.

하지만 정의보다 위쪽에서 호출이 되면 안되는데 이를 대비해 C언어처럼 먼저 선언만 해준다.

이는

asdf(); 로 할 수도

sub asdf; 로 할 수도 있고 두 개 이상인 경우

sub asdf; sub sdf; 와 같이할 수도 있고

use subs qw(asdf sdf); 와 같이 할 수도 있다.

sub routine 에 들어가는 변수들은 @_ 배열에 저장된다.

묵시적 return 값은 subroutine 마지막 행에 작성하면 된다.

명시적 return을 위해서는 subroutine안에 return $asd; 등으로 작성하면 된다.

sub의 실행속도를 높이기 위해 한번 계산한 값은 캐싱 하는 기법이 있는데

my %cache;

sub first_line {

my $filename=shift;

return $cache{$filename} if exists $cache{$filename};

open FILE, $filename or return “”;

my $line=<FILE>;

$cache{filename}=$line;

return $line;

}

과 같다.

함수 오버로딩이 가능한데

함수 내에서 리턴 타입을 판별할 수도 있다.

subroutine 내부에서 wantarray 라는 함수를 호출하면 array형의 return인지 아닌지를 판별해준다.

MPlayer를 이용한 동영상 음원 추출

MPlayer는 원래 오픈 소스 동영상 재생기이지만

커맨드 라인을 통한 간단한 포멧 변환을 지원하기 때문에

다음과 같은 명령어로 test.avi 에서 test.mp3 로 음원을 추출할 수 있다.

mplayer -vo null -dumpaudio test.avi -dumpfile test.mp3

이 작업을 폴더 내의 모든 avi 파일에 적용하기 위해서

Perl 스크립트로 짜 보면

#!/usr/bin/perl
#avi2mp3.plx
use strict;
use warnings;

opendir(DIR, ".") or die "$!\n";
my @files = readdir(DIR);
closedir DIR;

foreach(@files){
	my $filename = $_;
	next if $_ = /^\.\.?$/;

	$_ = $filename;
	next unless (-f $_);

	$_ = $filename;
	next unless $_ = /^(.*)\.avi$/;

	$filename = $1;

	print "Extracting mp3 from $filename\.avi\n";
	my $cmd = "mplayer -vo null -dumpaudio $filename\.avi -dumpfile $filename\.mp3";
	system($cmd);
}

와 같이 쓸 수 있다.