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인지 아닌지를 판별해준다.
위로 스크롤