Perl 문법설명
2015.06.19 17:07
출처 : http://ttongfly.net/zbxe/?document_srl=45342&mid=scriptprogramming&listStyle=&cpage=
Perl 문법설명
다음의 기사는 월간 프로그램 세계 1997년 6월호 특집기사로 실렸던 것입니다. 특집기사는 총 3부로 이루어져 있는데, 1부는 Perl의 소개, 2부는 Perl의 문법, 3부는 Perl을 이용한 CGI 예제 프로그램 작성으로 구성되어 있습니다. 제가 맡은 부분은 2부였고 총 분량의 절반에 해당합니다. 1부와 3부는 김대신(웹데이타뱅크)씨가 맡으셨습니다. 다음의 글은 제가 초안으로 작성한 텍스트 파일을 HTML문서로 약간 손을 본 것입니다.
차례
- 소개
- Perl의 문법
- 변수(Variable)
- 수치(number)
- 문자열(string)
- scalar variable
- vector variable
- 특수한 변수(Special variable)
- 레퍼런스(reference)
- 배열의 배열, 해시의 배열, 배열의 해시
- 식(Expression)
- 기본 연산자
- 추가 연산자
- 기본 입출력 연산자
- 비교 연산자
- Control Structure(제어 구조)
- if
- unless
- while/until
- for
- foreach
- do/while, do/until
- goto
- next, last, redo
- 서브루틴(Subroutine)
- 정의와 사용
- my와 local
- 패턴 매칭(Pattern Matching)
- 정규 표현식(regular expression)
- match, substitute, translate
- 문자열 pattern 조작
- 변수(Variable)
2부. 펄의 문법
Perl의 저자, Larry Wall이 말했던 것처럼 Perl은 한 가지 일을 하기 위해 10가지 방법을 제시하는 언어이다. 어떻게(how) 할 것인지가 중요한 게 아니라 무엇을(what) 할 것인지를 먼저 생각하고 프로그래밍을 해야 할 것이다. 그러나 다양한 표현 방식들을 많이 익히면 익힐수록 프로그래머에게 더 많은 가능성이 열리는 셈이다. 다음의 글은 독자들이 기본적인 C프로그래밍을 이해할 수 있고 유닉스의 shell기반의 작업들에 무지하지 않음을 가정하고 쓰여진 것이다. 그러나 가능하면 초보자들도 이해할 수 있도록 쉬운 표현과 예제를 이용하였다. 다음의 설명은 Perl 5를 기준으로 쓰여졌으나, Perl 4에서도 무난하게 사용 가능할 것이다.
1. 변수(Variable)
기본적으로 Perl은 변수에 대해, C와 같이 강력한 type checking을 하지 않는다. 다시 말해서 '값이 어떤 방식으로 저장되어있는가'는 '어떻게 사용할 것인가'와는 별개의 문제라는 것이다. C프로그래밍에 익숙한 사용자라면 int c = 'x'; 으로 정의된 변수 c가 문자형으로도 정수형으로도 사용 가능한 것을 떠올릴 수 있을 것이다. 그런 것을 확장해서 생각해보면 Perl의 변수들은 여러 형태로 사용할 수 있다. 그것은 Perl 인터프리터(interpreter;해석기)가 내부적으로 자동 변환해 주기 때문에 가능한 것이다.
1) 수치(number)
Perl에는 정수형 수치는 존재하지 않는다. 모든 수치는 double-precision floating point형 수치로 존재한다. 다음과 같은 형태의 수치는 float literal(소수형 상수)이다.
111.25 23.25e91 -12.5e29 -12e-34 3.2E-23
다음과 같은 형태의 수치는 integer-literal(정수형 상수)이다. 숫자 앞에 0이나 0x를 붙여쓰게 되면 각각 8진수와 16진수를 의미하게 된다.
342 -2423 0377 -0xf0
$str1 = 'hellonneveryone'; $str2 = "hellonneveryone"; print $str1 . "n"; print $str2 . "n";
두 문장은 quotation mark가 다르다는 점을 제외하고는 차이점이 없다. 그런데 출력결과는 다음과 같이 다르게 된다.
hellonneveryone # 이것은 str1의 출력 결과이다. hello # 이것은 str2의 출력 결과이다. everyone
$str0 = "I'm a boy."; $str1 = 'hello $str0'; $str2 = "hello $str0"; print $str1 . "n"; print $str2 . "n";
hello $str0 # str1의 출력 결과 hello I'm a boy. # str2의 출력 결과
single-quote 문자열에서 single-quote(')를 표현하는 방법은 backslash뒤에 single-quote를 쓰는 것이다.
print 'I'm a boy.'; # 출력 결과 I'm a boy.
다음은 double-quote안에서 특별한 효과를 가지는 escape character의 종류와 그 의미에 관한 표이다.
$time_of_today = `date`; print $time_of_today; # 출력 결과 Mon Apr 27 20:59:04 KST 1998
$keyword = 'doc'; print `ls | grep $keyword`;
jdbcprog.doc vi.doc xprog.doc
다음의 표는 quotation의 여러 가지 방법에 대해 정리한 것이다.
관습적 사용 | 일반적 사용 | 의미 | interpolation여부 |
'' | q// | 문자열상수 | x |
"" | qq// | 문자열상수 | o |
`` | qx// | 실행명령 | o |
() | qw// | list | x |
// | m// | pattern match | o |
s/// | s/// | substitution | o |
y/// | tr/// | translation | x |
$abc = q$I'm a boy. You're a girl.$; $def = qq#Hello,neveryone#; $ghi = q& while (test != 0) { i++; printf("%d", i); } &;
$abc $ABC $account_number_of_bank1 $account_number_of_bank2 $xyz001
@certain_list = ("abc", "def", "123"); @quoted_list = qw( 1, 2, 3, 4, 5, 6, 7, 8, ); %a_special_hash = (('test', "hello"), ('verify', 123)); %list_like_hash = ("red", 0xf00, "green", 0x0f0, "blue", 0x00f); %another_special_hash = ( red => 0xf00, green => 0xf00, blue => 0xf00, );
vector variable은 다른 vector 형태의 variable을 포함하여 지정할 수 있다.
@next_list = ("abc", "def", "123", @previous_list); %general_hash = (%a_special_hash, %list_like_hash);
print "@certain_list"; print @certain_list;
abc def 123 abcdef123
print "%a_special_hash"; print %a_special_hash;
list와는 달리 hash의 경우 interpolation이 일어나지 않음을 알 수 있다.
testhelloverify123 %a_special_hash
print $a_special_hash{'test'}; $key = 'verify'; print $a_special_hash{$key};
print $colors[0]; $id_list[3]++; print @month[8..11]; # @month[8..11]는 @month[8, 9, 10, 11]과 같다. $b = $namelist[$number];
list 단위의 연산도 가능하다. 대표적인 것으로 list assignment가 있다.
($a, $b, $c) = (3, 4, 5); @array = ('a', 'b', 'c', 'd');
vector variable 중에는 어떤 값도 가지지 않는 변수가 존재할 수 있는데, 이런 것을 null list라고 하며 ()로 표현한다.
@a = ();
use English;
$_ = 'abcdefghi'; /def/; print "$`:$&:$'n";
/Version: (.*)|Revision: (.*)/ && ($rev = $+);
use FileHandle;
$| | $OUTPUT_FLUSH_NUMBER | autoflush HANDLE EXPR | 값을 0이 아닌 값으로 지정하면, write또는 print문장 후에 fflush(3)함수를 호출하여 현재 선택된 output channel로 출력을 강제한다. |
$% | $FORMAT_PAGE_NUMBER | format_page_nubmer HANDLE EXPR | 현재 선택된 output channel의 현재 page 번호이다. |
$= | $FORMAT_LINES_PER_PAGE | format_lines_per_page HANDLE EXPR | 현재 선택된 output channel의 현재 page 길이(프린트 가능한 line의 수)이다. |
$- | $FORMAT_LINES_LEFT | format_lines_left HANDLE EXPR | 현재 선택된 output channel의 남아있는 line의 수이다. |
$~ | $FORMAT_NAME | format_name HANDLE EXPR | 현재 선택된 output channel의 현재 report format의 이름이다. |
$~ | $FORMAT_TOP_NAME | format_top_name HANDLE EXPR | 현재 선택된 output channel의 현재 top-of-page format의 이름이다. |
use FileHandle; use English; print '$| = '."$|n"; print '$% = '."$%n"; print '$- = '."$-n"; print '$~ = '."$~n"; print '$^ = '."$^ n"; print '$= = '."$=n";< print '$= = '."$FORMAT_LINES_PER_PAGEn"; format_lines_per_page STDOUT 30; print '$= = '."$FORMAT_LINES_PER_PAGEn"; print '$= = '."$=n";
특정 filehandle인 HANDLE에 per-filehandle special variable을 지정해주는 예제는 다음과 같다.
select((select(HANDLE), $| = 1, $^ = 'mytop')[0]);
$_ | $ARG | default input string, standard input이나 첫 번째 argument로 넘겨진 파일을 읽을 때 넘겨져 오는 string을 의미한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$. | $INPUT_LINE_NUMBER $NR | 마지막으로 읽힌 filehandle의 현재 input line number이다. 여러 argument로 넘겨진 파일들을 구분하지 않으므로, 다른 파일로 바뀌더라도 line number가 계속 증가하게 된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$/ | $INPUT_RECORD_SEPARATOR $RS | input record를 구분해주는 string을 의미하며 default값은 newline character이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$, | $OUTPUT_FIELD_SEPARATOR $OFS | output field를 구분해주는 string이며, print 연산자에서 사용된다. 일반적으로는 comma(,)가 separator로 사용된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$ | $OUTPUT_RECORD_SEPARATOR $ORS | output record를 구분해주는 string으로서 보통은 print 연산자가 record뒤에 newline내지는 record separator을 찍어주지 않기 때문에 필요할 경우, 지정하여야 한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$" | $LIST_SEPARATOR | list의 구분자로 사용되는 string을 지정하는 변수이다. 기본 값으로 space가 지정되어 있다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$; | $SUBSCRIPT_SEPARATOR $SUBSEP | 다차원 배열을 만들기 위해 list내에서 변수들을 나열할 경우, 그 변수들이 하나의 record로 인식되어야 하는데, 그것을 위해서 list내의 각 변수들을 join하는데 사용하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^L | $FORMAT_FORMFEED format_formfeed HANDLE EXPR |
print할 때, output의 format에서 formfeed로 사용될 string을 지정하는 변수로서, 기본 값은 "f"이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$: | $FORMAT_LINE_BREAK_CHARACTERS format_line_break_characters HANDLE EXPR |
연속적인 field를 잘라야 하는 경우 그 기준이 되는 character의 집합을 정의하는 변수이다. default로 "n-", 다시 말해서 newline과 hyphen이 사용된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^A | $ACCUMULATOR | format line을 위한 write accumulator의 현재 값을 지정하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$# | $OFMT | Perl5에서는 사용되지 않는, 이전 버전과의 호환성을 위해 제공되는 변수로, 숫자를 출력하기 위한 output format을 지정하는 변수이다. 초기 값은 %.14g 이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$? | $CHILD_ERROR | 마지막 실행 문에서 return되는 status값이다. 상위 8비트는 child process의 exit value이고, 하위 8비트는 어떤 signal을 받았는지와 core dump가 일어났는지의 여부에 대한 정보를 포함한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$! | $OS_ERROR $ERRNO | error에 관한 정보를 포함하는 변수로서, 사용되는 문맥에 따라 error 번호 또는 error string을 보여주게 된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$@ | $EVAL_ERROR | eval 명령으로부터 발생하는 error message를 담는 변수이다. null로 값이 지정될 경우 성공적으로 실행되었음을 의미한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$$ | $PROCESS_ID $PID | 현재 script를 실행하고 있는 Perl프로그램의 process id(번호)를 지니고 있는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$< | $REAL_USER_ID $UID | 현재 process의 real user id(uid)를 지닌 변수로서, process를 실행시킨 사용자의 id를 의미한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$> | $EFFECTIVE_USER_ID $EUID | 현재 process의 effective user id(euid)를 지닌 변수로서, process의 원래 소유자의 id를 의미한다. 일반적인 process의 경우, uid와 같은 값을 가지지만, setuid bit가 켜져 있는 실행파일의 경우, uid는 실행자의 id로, euid는 파일 소유자의 것으로 지정된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$( | $REAL_GROUP_ID $GID | 현재 process의 real group id(gid)를 지정하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$) | $EFFECTIVE_GROUP_ID $EGID | 현재 process의 effective group id(egid)를 지정하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
출처 : http://ttongfly.net/zbxe/?document_srl=45342&mid=scriptprogramming&listStyle=&cpage=
Perl 문법설명
다음의 기사는 월간 프로그램 세계 1997년 6월호 특집기사로 실렸던 것입니다. 특집기사는 총 3부로 이루어져 있는데, 1부는 Perl의 소개, 2부는 Perl의 문법, 3부는 Perl을 이용한 CGI 예제 프로그램 작성으로 구성되어 있습니다. 제가 맡은 부분은 2부였고 총 분량의 절반에 해당합니다. 1부와 3부는 김대신(웹데이타뱅크)씨가 맡으셨습니다. 다음의 글은 제가 초안으로 작성한 텍스트 파일을 HTML문서로 약간 손을 본 것입니다. 차례
2부. 펄의 문법
111.25 23.25e91 -12.5e29 -12e-34 3.2E-23
342 -2423 0377 -0xf0 $str1 = 'hellonneveryone'; $str2 = "hellonneveryone"; print $str1 . "n"; print $str2 . "n";
hellonneveryone # 이것은 str1의 출력 결과이다. hello # 이것은 str2의 출력 결과이다. everyone $str0 = "I'm a boy."; $str1 = 'hello $str0'; $str2 = "hello $str0"; print $str1 . "n"; print $str2 . "n"; hello $str0 # str1의 출력 결과 hello I'm a boy. # str2의 출력 결과
print 'I'm a boy.'; # 출력 결과 I'm a boy.
$time_of_today = `date`; print $time_of_today; # 출력 결과 Mon Apr 27 20:59:04 KST 1998 $keyword = 'doc'; print `ls | grep $keyword`; jdbcprog.doc vi.doc xprog.doc
$abc = q$I'm a boy. You're a girl.$; $def = qq#Hello,neveryone#; $ghi = q& while (test != 0) { i++; printf("%d", i); } &; $abc $ABC $account_number_of_bank1 $account_number_of_bank2 $xyz001 @certain_list = ("abc", "def", "123"); @quoted_list = qw( 1, 2, 3, 4, 5, 6, 7, 8, ); %a_special_hash = (('test', "hello"), ('verify', 123)); %list_like_hash = ("red", 0xf00, "green", 0x0f0, "blue", 0x00f); %another_special_hash = ( red => 0xf00, green => 0xf00, blue => 0xf00, );
@next_list = ("abc", "def", "123", @previous_list); %general_hash = (%a_special_hash, %list_like_hash); print "@certain_list"; print @certain_list; abc def 123 abcdef123 print "%a_special_hash"; print %a_special_hash;
testhelloverify123 %a_special_hash print $a_special_hash{'test'}; $key = 'verify'; print $a_special_hash{$key}; print $colors[0]; $id_list[3]++; print @month[8..11]; # @month[8..11]는 @month[8, 9, 10, 11]과 같다. $b = $namelist[$number];
($a, $b, $c) = (3, 4, 5); @array = ('a', 'b', 'c', 'd');
@a = (); use English;
$_ = 'abcdefghi'; /def/; print "$`:$&:$'n"; /Version: (.*)|Revision: (.*)/ && ($rev = $+); use FileHandle;
use FileHandle; use English; print '$| = '."$|n"; print '$% = '."$%n"; print '$- = '."$-n"; print '$~ = '."$~n"; print '$^ = '."$^ n"; print '$= = '."$=n";< print '$= = '."$FORMAT_LINES_PER_PAGEn"; format_lines_per_page STDOUT 30; print '$= = '."$FORMAT_LINES_PER_PAGEn"; print '$= = '."$=n";
select((select(HANDLE), $| = 1, $^ = 'mytop')[0]);
$foo{$a, $b, $c} $foo{join($;, $a, $b, $c)}
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin"; sub sighandler { local($sig) = @_; print "Closing log file...n"; close(LOG); exit(0); } $SIG{'INT'} = 'handler';
$scalarref = $foo; # $foo는 일반변수, 는 reference하는 연산자 $constref = 3.24; # hard reference는 값에 대한 reference이다. $arrayref = @array1; $hashref = %hash2; $globref = *STDOUT; # *는 typeglob이며, 모든 타입을 가리킨다. $subref = &subroutine3; print $$scalarref; # print $foo;와 동일하다. $$constref # 3.24와 동일하다. $$hashref{'key1'} # $hash2{'key1'}과 동일하다. &$subref; # subroutine3를 호출하게 된다. shift(@$arrayref); # @array1에 대해 shift연산을 하는 것과 같다. $multiref = 123; # 123에 대해 연산을 4번 시행 print $$$$$multiref; # $multiref에 대해서 $연산을 4번 시행 $arrayref = [1, 2, [3, 4, 5]]; # anonymous array reference $hashref = { 'Meg' => 'Ryan', # anonymous hash reference 'Billy' => 'Christal' }; $subref = sub { print "When Harry met Sallyn"; # anonymous subroutine reference }; @array = (1, 2, (3, 4, 5)); %hash = ( 'Meg' => 'Ryan', # anonymous hash reference 'Billy' => 'Christal' ); &subroutine1; sub subroutine1 { print "Sleepless in Seattlen"; # anonymous subroutine reference }; $$arrayref[0] = "first"; ${$arrayref}[0] = "first"; $arrayref->[0] = "first"; $$hashref{'key2'} = "McLean"; ${$hashref}{'key2'} = "McLean"; $hashref->{'key2'} = "McLean"; $arrayref->[3] = "list-item1"; $arrayref->[3]->[4] = "multi-dimensional-item2"; $arrayref->[3][4] = "multi-dimensional-item2"; $$arrayref[3][4] = "multi-dimensional-item2"; $ref_list_of_list = [ ["separator", "delimiter", "terminator"], ["long", "short", "int", "signed", "unsigned"], ["physics", "chemistry", "computer"], ]; print $ref_list_of_list[0][2]; # terminator가 출력된다. print $ref_list_of_list->[2][1]; # electronics가 출력된다. print $ref_list_of_list->[1]->[3]; # signed가 출력된다. $var1 = "test"; $sr = "var1"; $$sr = "verify"; # $var1 eq "verify" @var2 = ("hello", "program", "world"); $sr = "var2"; push(@$sr, "perl"); # @var2 eq ('hello', 'program', 'world', 'perl') @list_of_list = ( ("separator", "delimiter", "terminator"), ("long", "short", "int", "signed", "unsigned"), ("physics", "chemistry", "computer"), ); print $list_of_list[0][2]; print $list_of_list[2][1]; print $list_of_list[1][3];
@list_of_list = ( ["separator", "delimiter", "terminator"], ["long", "short", "int", "signed", "unsigned"], ["physics", "chemistry", "computer"], ); print $list_of_list[0][2]; # terminator가 출력된다. print $list_of_list[2][1]; # electronics가 출력된다. print $list_of_list[1][3]; # signed가 출력된다.
%hash_of_list = ( token => ["separator", "delimiter", "terminator"], type => ["long", "short", "int", "signed", "unsigned"], science => ["physics", "chemistry", "computer"], ); print $hash_of_list{'token'}->[1]; # delimiter가 출력된다. print $hash_of_list{'type'}[0]; # long이 출력된다. print $hash_of_list{science}; # ARRAY(0xb2074)같은 정보가 출력된다. print $hash_of_list{science}->[2]; # computer이 출력된다. print @$hash_of_list{science}; # 아무 것도 출력되지 않는다. print @{$hash_of_list{science}}; # physicschemistrycomputer 출력 %hash_of_hash = ( token => { s => "separator", d => "delimiter", t => "terminator" }, type => { l => "long", s => "short", i => "int" }, science => { e => "chemistry", c => "computer", }, ); print $hash_of_hash{token}->{s}; # separator 출력 print $hash_of_hash{type}{i}; # int 출력 print $hash_of_hash{science}; # HASH(0xb205c)같은 정보가 출력된다.
2 + 3 # 5 5.1 - 2.4 # 2.7 3 * 12 # 36 14 / 2 # 7 10.2 / 0.3 # 34 10 / 3 # 3.33333... if (3 > 4) { print "3 is greater than 4.n"; } else { print "3 is not greater than 4.n"; # 비교문이 거짓이므로 여기가 실행됨 }
$b = "Hello, "; $c = "world"; $a = $b . $c; # $a = "Hello, world" $a = "boy"; $b = $a x 3; # $b = "boyboyboy" $c = $a x 4.2; # $b = "boyboyboyboy", 4.2는 4로 cast된다.
$a *= 3; # $a = $a * 3; $b .= "n"; # $b = $b . "n" $c ||= 2; # $c = $c || 2, $c가 2가 아니면 2의 값을 대입한다.
$a = " 3.5abcd" * 4; print $a; # 3.5 * 4 = 14가 출력된다. $b = "3" + "4"; # $b = 7
print "boy" . (3 * 2); # boy6가 출력된다. print "boy" x (3 * 2); # boyboyboyboyboyboy가 출력된다.
while (<>) { chomp; # default input string의 마지막 n을 제거한다. next unless -f $_; # 정규파일이 아닌 경우에는 다음으로 넘어간다. } stat($file); print "Readablen" if -r _; # _는 마지막으로 사용된 filehandle이다. print "Writablen" if -w _; # readable, writable, executable한지 체크한다. print "Executablen" if -x _; &newfile if -M $file < 5; # mtime이 5일 이내라면 서브루틴을 호출한다.
$input =
print while
open(FILE, "test.c"); $_ = 이 예제는 test.c라는 파일을 FILE이라는 filehandle을 통해서 다루게 되고 default input string에 한 줄 입력을 받아서 그것을 다시 출력해주는 작업을 하게 된다. 그러나 대개는 한 줄만 입력을 받는 게 아니라 파일 전체에 대해서 여러 줄의 입력을 받아야 하므로 loop안에서 사용하거나 리스트에 저장했다가 shift연산자를 사용하여 꺼내어 사용할 수 있다. 그러나 리스트에 파일의 큰 내용이 저장되는 것은 시스템에 부하를 주게 되므로 loop를 사용하는 방법을 익히도록 하자.
while ($input = 이 예제는 FILE을 통해 $input에 입력을 받고 그 line을 comment기호로 감싸는 작업을 수행하는 것이다. Perl 프로그램이 filter로 사용되는 게 아니라면 대개는 프로그램의 argument로 파일 이름을 넘겨받아 사용하게 되는데, 이것은 아주 간단하다. 다음은 argument로 넘겨진 모든 파일을 열어서 한 줄씩 입력을 받아서 출력하는 예이다.
while (<>) { print; } 이 코드는 다음과 동일한 의미를 가진다.
@ARGV = ('-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV) or warn "Can't open $ARGV: $!n"; while ( argument로 넘겨받는 파일이름에 대해서는 신경쓸 필요 없이 <>만 사용하면 각 파일에 대해서 open하고 읽어들이는 과정이 모두 자동적으로 실행되는 것이다. b) 출력 print연산을 사용하는 경우에는 default로 출력의 방향이 STDOUT으로 정해진다. 그러므로 다음의 세 문장은 같은 의미를 가진다.
print "Hello worldn"; print STDOUT "Hello worldn"; print STDOUT Hello, " ", world, "n"; STDOUT뒤에 ,를 찍지 않도록 주의하자. STDOUT은 출력 대상이 아니라 출력의 방향이기 때문이다. 특정 파일에 대해서 출력을 하기 위해서는 미리 쓰기 mode로 open을 해야 하고 그 이후에 print 연산에 출력 방향으로 그 파일의 filehandle을 지정하면 된다.
open(OUTPUT, "> output.log"); print OUTPUT "Result : All men are alive.n"); shell에서 사용하던 방식의 token을 이용한 출력방법도 있다. 이것을 here document 문법이라고 하며 token을 일종의 quote로 생각하는 것이다. 여러 줄에 걸쳐진 출력에 대해서 문서를 쓰듯이 출력할 수 있다는 게 장점이다.
print OUTPUT << EOF But most of payload are lost. Estimation of loss are still being carried. EOF print 연산자는 EOF라는 토큰을 quote로 간주하고 두개 사이의 텍스트를 지정된 출력방향으로 내보내게 된다. 토큰에 따라서 보다 정교한 출력 방법이 있는데, 여기서는 몇 가지만 더 살펴보기로 하겠다.
print << "" x 10 Hello, world! 이 예제는 quote가 null string이므로(그러므로 ""조차 생략 가능하다.) 다음 줄만을 출력 대상으로 삼게 되고 print 연산을 10번 수행하게 된다.
print << `ANYTOKEN` id echo hello ANYTOKEN token을 감싸는 것이 back-quote(backtick)임에 유의하라. back-quote는 명령을 실행시켜주는 역할을 한다. 그러므로 두 토큰 사이에 존재하는 id와 echo hello라는 명령이 실행된 결과가 출력되게 된다. c) 에러 출력 에러는 파일로 보낼 수도 있지만, STDERR로 모아서 보내는 것이 일반적이다. 그러므로 print의 출력방향을 STDERR로 명시하면 된다.
print STDERR "Can't find such a file!n"; 4) 비교 연산자 Perl에서는 문자열에서 사용되는 논리연산자와 수치에서 사용되는 논리연산자가 따로 제공된다. 다음의 표를 참조하라.
|
$PROGRAM_NAME | 현재 실행중인 Perl script의 이름을 지정하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$[ | 배열의 첫 번째 원소의 index, 또는 substring의 첫 번째 글자의 index를 지정하는 변수이다. 기본적으로는 0번 원소부터 배열이 시작하지만, 1번 원소부터 배열이 시작하도록 1로 값을 바꿀 수 있다. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$] | $PERL_VERSION | Perl의 version과 patch level을 알려주는 변수로서, 5.004는 5번째 version에 4번째 patch level임을 의미한다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^D | $DEBUGGING | debugging flag(-D switch)가 켜져 있는지에 관한 정보를 담고 있는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^F | $SYSTEM_FD_MAX | 현재 open되어 사용되고 있는 file descriptor의 최대 번호를 지정하는 변수이다. 보통 프로그램이 시작하게 되면 자동으로 0, 1, 2번이 STDIN, STDOUT, STDERR로 설정된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^H | Perl compiler의 내부 컴파일 힌트에 관한 정보를 담는 변수이다. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^I | $INPLACE_EDIT | inplace-edit extension의 값을 저장하는 변수이다. 이 값은 -i switch에 의해 지정된다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^O | $OSNAME | 현재 사용되고 있는 Operating System의 이름을 저장하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^P | $PERLDB | Perl debugger가 자신을 debug하지 않도록 꺼주는 내부 flag 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^T | $BASETIME | script가 실행되기 시작한 시각을 지정하는 변수이다. Unix system에서는 70년 1월 1일 0시 0분 0초(epoch)로부터의, 초단위 시간이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^W | $WARNING | -w switch에 의해 지정되는 warning(경고) 여부의 값을 저장하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$^X | $EXECUTABLE_NAME | Perl 바이너리가 실행 시에 가지게 되는 이름을 지정하는 변수이다. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$ARGV | argument로 넘겨져 들어온 파일의 이름이다. |
$foo{$a, $b, $c} $foo{join($;, $a, $b, $c)}
@ARGV | 넘겨져 들어온 command-line argument의 list를 저장하는 변수이다. |
@INC | do, require, use등의 operator를 사용할 때 필요한 Perl script를 찾는 디렉토리를 지정하는 변수이다. -I switch를 사용하여 지정된다. lib module을 사용하여도 지정 가능하다. |
@F | -a switch를 사용한 경우에, input line을 분리해 넣어줄 변수의 array를 지정하는 list 변수이다. |
%INC | module로 사용될 Perl script의 이름과 그 script의 절대경로를 저장해놓은 hash 변수이다. |
%ENV | shell에서 넘겨져 온 hash type의 환경변수이다. 환경변수의 이름과 그 값을 hash해 놓았다. |
%SIG | signal과 그에 해당하는 signal handler를 지정하는 hash 변수이다. |
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin";
sub sighandler { local($sig) = @_; print "Closing log file...n"; close(LOG); exit(0); } $SIG{'INT'} = 'handler';
ARGV | @ARGV에서 저장된 argument로 넘겨진 file들을 다루는 filehandle이다. |
STDERR | standard error에 대한 filehandle이다. |
STDIN | standard input에 대한 filehandle이다. |
STDOUT | standard output에 대한 filehandle이다. |
DATA | Perl script에서 __END__라는 token뒤쪽에 나오는 모든 자료에 대한 filehandle이다. |
_(underline) | 마지막으로 다루었던 파일에 대한 정보를 cache로 저장하고 있는 filehandle이다. |
$scalarref = $foo; # $foo는 일반변수, 는 reference하는 연산자 $constref = 3.24; # hard reference는 값에 대한 reference이다. $arrayref = @array1; $hashref = %hash2; $globref = *STDOUT; # *는 typeglob이며, 모든 타입을 가리킨다. $subref = &subroutine3;
print $$scalarref; # print $foo;와 동일하다. $$constref # 3.24와 동일하다. $$hashref{'key1'} # $hash2{'key1'}과 동일하다. &$subref; # subroutine3를 호출하게 된다. shift(@$arrayref); # @array1에 대해 shift연산을 하는 것과 같다.
$multiref = 123; # 123에 대해 연산을 4번 시행 print $$$$$multiref; # $multiref에 대해서 $연산을 4번 시행
$arrayref = [1, 2, [3, 4, 5]]; # anonymous array reference $hashref = { 'Meg' => 'Ryan', # anonymous hash reference 'Billy' => 'Christal' }; $subref = sub { print "When Harry met Sallyn"; # anonymous subroutine reference };
@array = (1, 2, (3, 4, 5)); %hash = ( 'Meg' => 'Ryan', # anonymous hash reference 'Billy' => 'Christal' ); &subroutine1; sub subroutine1 { print "Sleepless in Seattlen"; # anonymous subroutine reference };
$$arrayref[0] = "first"; ${$arrayref}[0] = "first"; $arrayref->[0] = "first"; $$hashref{'key2'} = "McLean"; ${$hashref}{'key2'} = "McLean"; $hashref->{'key2'} = "McLean";
$arrayref->[3] = "list-item1"; $arrayref->[3]->[4] = "multi-dimensional-item2"; $arrayref->[3][4] = "multi-dimensional-item2"; $$arrayref[3][4] = "multi-dimensional-item2";
$ref_list_of_list = [ ["separator", "delimiter", "terminator"], ["long", "short", "int", "signed", "unsigned"], ["physics", "chemistry", "computer"], ]; print $ref_list_of_list[0][2]; # terminator가 출력된다. print $ref_list_of_list->[2][1]; # electronics가 출력된다. print $ref_list_of_list->[1]->[3]; # signed가 출력된다.
$var1 = "test"; $sr = "var1"; $$sr = "verify"; # $var1 eq "verify" @var2 = ("hello", "program", "world"); $sr = "var2"; push(@$sr, "perl"); # @var2 eq ('hello', 'program', 'world', 'perl')
@list_of_list = ( ("separator", "delimiter", "terminator"), ("long", "short", "int", "signed", "unsigned"), ("physics", "chemistry", "computer"), ); print $list_of_list[0][2]; print $list_of_list[2][1]; print $list_of_list[1][3];
2차원 배열을 구현하기 위해서는 reference를 이용해야 한다.
@list_of_list = ( ["separator", "delimiter", "terminator"], ["long", "short", "int", "signed", "unsigned"], ["physics", "chemistry", "computer"], ); print $list_of_list[0][2]; # terminator가 출력된다. print $list_of_list[2][1]; # electronics가 출력된다. print $list_of_list[1][3]; # signed가 출력된다.
b) 배열의 해시
리스트를 해시 값으로 사용하여 해시를 만드는 것도 비슷한 방법에 의해 가능하다.
%hash_of_list = ( token => ["separator", "delimiter", "terminator"], type => ["long", "short", "int", "signed", "unsigned"], science => ["physics", "chemistry", "computer"], ); print $hash_of_list{'token'}->[1]; # delimiter가 출력된다. print $hash_of_list{'type'}[0]; # long이 출력된다. print $hash_of_list{science}; # ARRAY(0xb2074)같은 정보가 출력된다. print $hash_of_list{science}->[2]; # computer이 출력된다. print @$hash_of_list{science}; # 아무 것도 출력되지 않는다. print @{$hash_of_list{science}}; # physicschemistrycomputer 출력
%hash_of_hash = ( token => { s => "separator", d => "delimiter", t => "terminator" }, type => { l => "long", s => "short", i => "int" }, science => { e => "chemistry", c => "computer", }, ); print $hash_of_hash{token}->{s}; # separator 출력 print $hash_of_hash{type}{i}; # int 출력 print $hash_of_hash{science}; # HASH(0xb205c)같은 정보가 출력된다.
다만 주의할 것은 해시나 리스트는 해시의 키(key)로 사용할 수 없다는 것이다. 이유는 key는 단순한 문자열로 취급이 되기 때문이다. 리스트나 해시를 넣는다고 해도 문자열 이상의 의미를 가지지는 못하게 된다.
2. 식(Expression)
1) 기본 연산자
a) 수치 연산자
Perl은 수치에 대해서 사칙연산을 기본적으로 제공한다. +, -, *, /가 그에 해당하는 연산자이다. 그리고 FORTRAN과 같이 **에 의한 거듭제곱 연산도 가능하다. 나머지를 구하는 연산도 있는데, %를 연산자(operator)로 사용하며, 피연산자(operand) 모두를 정수로 취급한다. 반면에 나누기 연산자인 /는 피연산자 모두를 실수로 취급한다. 논리연산자인 <, <=, ==, >=, >, !도 사용 가능하다.
다음은 수치 연산자의 사용 예이다.
2 + 3 # 5 5.1 - 2.4 # 2.7 3 * 12 # 36 14 / 2 # 7 10.2 / 0.3 # 34 10 / 3 # 3.33333... if (3 > 4) { print "3 is greater than 4.n"; } else { print "3 is not greater than 4.n"; # 비교문이 거짓이므로 여기가 실행됨 }
b) 문자열 연산자
문자열 연산자에는 C에서는 볼 수 없는 연산자들이 많이 등장한다. 우선은 문자열들을 붙이는 연산자인 .(dot)이 있고, 문자열을 정수번 반복해서 붙여주는 x연산자도 있다. 다음의 예제를 참고하도록 하자.
$b = "Hello, "; $c = "world"; $a = $b . $c; # $a = "Hello, world" $a = "boy"; $b = $a x 3; # $b = "boyboyboy" $c = $a x 4.2; # $b = "boyboyboyboy", 4.2는 4로 cast된다.
c) 대입연산자(assignment operator)
대입연산자에는 C와 마찬가지로 =이 기본적인 연산자이다. 이밖에도 C에서 사용하는 대입연산자들은 거의 Perl에서 채택되어져 있다. +=, -=, *=, /=, &=, |=. ^=, %=가 그 예이다. 그 밖에도 .=, x=, ||=, **=, <<=, >>=의 연산자들이 있다. 이와 같은 대입연산자들은 %연산, .연산, x연산, ||연산을 수행한 후에 그 결과를 대입하는 것이므로 보충 설명이 없어도 이해에 어려움이 없을 것이다.
$a *= 3; # $a = $a * 3; $b .= "n"; # $b = $b . "n" $c ||= 2; # $c = $c || 2, $c가 2가 아니면 2의 값을 대입한다.
d) 연산자 우선 순위와 결합법칙
여러 연산자들의 결합순위와 우선 순위를 다음의 표로 정리해놓았다. 위쪽에 있는 연산자일수록 아래쪽 연산자들보다 우선 순위가 높다. 같은 줄에 있는 연산자들은 같은 우선 순위 가지게 되고 결합순위에 따라 연산의 순서가 정해진다.
결합순위 | 연산자 |
없음 | ++ -- |
우 | ! ~ -(단항연산) |
우 | ** |
좌 | =~ !~ |
좌 | * / % x |
좌 | + -(이항연산) . |
좌 | << >> |
없음 | file test operator |
없음 | named unary operator |
없음 | < <= > >= lt le gt ge |
없음 | == != <=> eq ne cmp |
좌 | & |
좌 | | ^ |
좌 | && |
좌 | || |
없음 | .. |
우 | ?:(삼항연산) |
우 | 대입 연산자 (+= -= 등) |
좌 | , |
없음 | list 연산자 |
e) 수치와 문자열 상호변환
Perl은 수치와 문자열, 정수와 실수 사이의 변환을 자동으로 해준다. 수치 앞 뒤쪽에 오는 쓸데없는 문자들을 자동으로 제거해주므로 다음과 같은 연산이 가능하다.
$a = " 3.5abcd" * 4; print $a; # 3.5 * 4 = 14가 출력된다. $b = "3" + "4"; # $b = 7
Perl이 자동으로 변환해 주는 것은 문자열 또는 수치가 이중적인 의미를 가질 때, 앞쪽이나 뒤쪽에 위치하는 연산자가 필요로 하는 피연산자가 수치인가 문자열인가를 결정할 수 있기 때문이다.
print "boy" . (3 * 2); # boy6가 출력된다. print "boy" x (3 * 2); # boyboyboyboyboyboy가 출력된다.
괄호 안의 3 * 2이 먼저 수치로서 계산이 된다. 수치로 인식되는 이유는 *이 수치를 피연산자로 가지기 때문이다. 다음에는 문자열을 결합시켜주는 . 연산자를 만나게 되므로 (3 * 2)의 결과인 6을 문자열로 변환시켜서 인식하게 된다. 이러한 방식으로 자동변환이 일어나게 되므로 프로그래머는 사소한 것에 신경 쓰지 않아도 된다.
2) 추가 연산자
또 하나 프로그래머가 매달릴 필요가 없는 것은 연산자를 연산자로 볼 것인가 함수로 볼 것인가의 문제인데, Perl에서 제공되는 대개의 연산자는 연산자이면서 함수로 볼 수 있기 때문에 C처럼 ()를 반드시 써 줄 필요가 없다.
a) scalar operator
rand $a | 0과 $a 사이의 임의의 값(random number)을 반환한다. 0이상 $a미만의 범위의 소수를 구하게 된다. |
srand $a | random number를 만들어 낼 때 사용하는 seed값을 지정한다. srand(time^$$)처럼 현재시간을 알려주는 time연산자와 현재 프로세스의 번호를 지정하는 $$변수를 넣어서 사용하기도 한다. |
substr $a, $b, $c | $a라는 문자열에서 $b의 offset위치에 $c개만큼의 원소를 지정하게 된다. substr을 이용해서 $a에 새로운 값을 넣어주거나 $a에서 원소를 꺼내올 수 있다. $c부분은 생략 가능하다. |
index $a, $b, $c | 문자열 $a에서 $b가 나타나는 위치(offset)을 알려준다. $c부분은 찾기 시작하는 위치를 지정하는 것인데, 생략되면 0의 값이 대신 사용된다. |
chop $a | chop은 $a의 마지막 글자를 제거하는 연산자이며 Perl 5에서는 다음의 chomp을 권장한다. $a는 리스트라도 처리할 수 있다. |
chomp $a | chomp는 chop의 안전한 버전이며, $a의 마지막 글자가 $/변수($INPUT_RECORD_SEPARATOR, $RS)의 값을 가지면 제거하는 역할을 한다. 대개는 입력에 붙어서 들어오는 newline character를 제거할 때 사용한다. |
b) vector operator
shift @a | 리스트 @a의 가장 앞쪽에 있는 원소를 꺼내준다. |
unshift @a, $b | $b를 @a의 가장 앞쪽에 쑤셔 넣어 준다. |
pop @a | @a의 가장 뒤쪽에 있는 원소를 꺼내준다. |
push(@a, $b) | @a의 가장 뒤쪽에 $b를 추가해준다. |
splice @a, $b, $c, @d; | @a의 offset이 $b되는 곳에서 $c개의 원소를 지정할 때 사용한다. @d가 사용되는 경우에는 @d를 $c개의 원소와 바꾸어준다. @d가 생략되면 $c개의 원소를 반환한다. |
keys %a | 해시 변수 %a의 key를 모아서 리스트 형태로 반환한다. |
$a .. $b | ..은 범위연산자(range operator)라고 하는데, $a에서 $b까지의 값을 리스트 형태로 반환한다. $a와 $b에 들어갈 수 있는 값은 정수나 문자이다. 문자열을 사용하면 그 사이에 존재할 수 있는 모든 문자열 조합을 만들어 주기도 하는데, 시스템의 자원을 낭비하기 쉬우므로 조심해야 한다. |
, | comma(,) 연산자는 리스트에서 separator로 사용되는 comma와는 다른 의미를 가진다. comma 연산자는 ,뒤쪽의 값을 반환한다. ,로 여러 개의 값이 나열되면 마지막 값이 리턴 된다. |
sort @a | 리스트변수 @a를 정렬해준다. sort의 기준을 제시하는 비교함수나 블럭을 지정할 수도 있는데, 리스트 앞에 지정해준다. 이 때 비교함수나 블럭에서는 <=>, cmp 연산자와 논리연산자등을 사용하여 +1, -1, 0등의 값을 반환하도록 한다. |
reverse @a | 리스트의 원소의 순서를 반대 방향으로 바꾸어준다. |
grep PATTERN, @a grep FILETEST, @a |
리스트변수 @a를 읽어들여 패턴매치나 파일 테스트를 해서 성공할 경우, 그 리스트의 원소인 line이나 string을 반환한다. |
join $b, @a | @a의 원소들을 $b를 delimiter로 하여 묶어 하나의 문자열로 반환한다. |
split PATTERN, $a, $b | 문자열 $a를 PATTERN에 나오는 character를 delimiter로 해서 나누어 리스트형태로 반환한다. $b를 사용하게 되면 그 값에 해당하는 개수까지 원소들을 생성해준다. |
c) file test operator
다음은 파일에 대한 조건식을 만드는 operator을 정리한 표이다. 다음의 테스트는 참/거짓의 값을 가지거나 특정한 결과 값을 return해 준다.
-r | 파일을 읽을 수(readable) 있는가? |
-w | 파일을 쓸 수(writable) 있는가? |
-x | 파일을 실행시킬 수(executable) 있는가? |
-o | 파일이 $euid의 사용자 소유인가? |
-R | 파일이 $uid의 사용자에 의해 읽혀질 수 있는가? |
-W | 파일이 $uid의 사용자에 의해 쓰여질 수 있는가? |
-X | 파일이 $uid의 사용자에 의해 실행가능한가? |
-O | 파일이 $uid의 사용자 소유인가? |
-e | 파일이 존재하는가? |
-z | 파일의 크기가 0인가? |
-s | 파일의 크기(size) |
-f | 파일이 정규파일(디렉토리가 아닌)인가? |
-d | 파일이 디렉토리인가? |
-l | 파일이 symbolic link인가? |
-p | 파일이 FIFO와 같은 named pipe인가? |
-S | 파일이 socket인가? |
-b | 파일이 block special file인가? |
-c | 파일이 character special file인가? |
-t | filehandle이 tty(terminal)에 열려 있는가? |
-u | setuid bit이 켜져 있는 파일인가? |
-g | setgid bit이 켜져 있는 파일인가? |
-k | sticky bit이 켜져 있는 파일인가? |
-T | 파일이 텍스트(text) 파일인가? |
-B | 이진(binary) 파일인가? |
-M | file의 최종 수정 시간(modification time, mtime) |
-A | file의 최종 접근 시간(last access time, atime) |
-C | file의 최종 변경 시간(inode change time, ctime) |
다음은 file test를 이용한 조건식의 예이다.
while (<>) { chomp; # default input string의 마지막 n을 제거한다. next unless -f $_; # 정규파일이 아닌 경우에는 다음으로 넘어간다. } stat($file); print "Readablen" if -r _; # _는 마지막으로 사용된 filehandle이다. print "Writablen" if -w _; # readable, writable, executable한지 체크한다. print "Executablen" if -x _; &newfile if -M $file < 5; # mtime이 5일 이내라면 서브루틴을 호출한다.
3) 기본 입출력 연산자
입출력이란 프로그램이 자료를 외부세계에서 넘겨받고 그 자료를 처리한 결과를 외부세계에 넘겨주는 과정을 의미한다. Perl에서 가능한 방법은 파일을 이용한 것이고, 프로그래머는 filehandle이라는 것을 가지고 파일을 다룰 수 있게 된다. 파일을 열어서 filehandle을 지정하는 것은 open함수를 사용하면 되고, 더 이상 사용하지 않게 된 파일을 닫고 filehandle의 사용을 포기하는 것은 close함수를 이용하면 된다.
그러나 입출력 과정에 filehandle을 매번 사용한다는 것은 프로그램 작성에 상당한 불편을 안겨줄 것이다. 그리하여 Perl에서는 Unix시스템과 마찬가지로 표준입력(STDIN), 표준출력(STDOUT), 표준에러(STDERR)를 제공한다. 표준입력이란 키보드를 통해 자료를 입력받거나, 다른 프로그램에서 파이프나 redirection을 통해 자료를 넘겨받는 것이다. 반면에 표준출력은 print 연산이나 printf를 통해서 화면으로 결과를 출력하는 것이고, 표준에러는 화면에 에러메시지를 보여주는 것이다.
a) 입력
일반적으로 키보드로부터의 입력은
$input =; @input = ;
과 같은 형태로 받아들일 수 있다. $input이나 @input에는 사용자가 키보드를 통해 눌렀던 모든 키 입력이 문자열 또는 리스트의 형태로 저장된다.
Perl에서 즐겨 사용되는 입력방식에는 다음과 같은 것들이 있다. 짧은 코드에서 긴 코드까지 모두 같은 효과를 가지며, 문맥적으로 같은 의미를 가진다.
print whileprint $_ while ; print $_ while definded($_ = ); for (; ;) { print; } for (; ;) { print $_; } while ( ) { print; } while ( ) { print $_; } while (defined($_ = )) { print $_ };
$_는 default input string을 저장하는 변수로서 대개의 연산자에서 생략 가능하다. 거꾸로 말해서, 연산자만 나오는 경우는 대개 $_를 염두에 둔 것이라고 볼 수 있다. 에서 들어온 모든 입력은 $_에 자동으로 저장된다. $_대신에 다른 변수를 사용해도 별로 상관은 없으나, 생략해서 사용할 수는 없다.
STDIN같은 표준입출력에 관련된 filehandle은 굳이 open의 과정이 필요 없으나, 일반적인 파일에 대한 filehandle은 open의 과정이 명시되어야 한다.
open(FILE, "test.c"); $_ =; print;
이 예제는 test.c라는 파일을 FILE이라는 filehandle을 통해서 다루게 되고 default input string에 한 줄 입력을 받아서 그것을 다시 출력해주는 작업을 하게 된다. 그러나 대개는 한 줄만 입력을 받는 게 아니라 파일 전체에 대해서 여러 줄의 입력을 받아야 하므로 loop안에서 사용하거나 리스트에 저장했다가 shift연산자를 사용하여 꺼내어 사용할 수 있다. 그러나 리스트에 파일의 큰 내용이 저장되는 것은 시스템에 부하를 주게 되므로 loop를 사용하는 방법을 익히도록 하자.
while ($input =) { print "/* $input */n"; }
이 예제는 FILE을 통해 $input에 입력을 받고 그 line을 comment기호로 감싸는 작업을 수행하는 것이다.
Perl 프로그램이 filter로 사용되는 게 아니라면 대개는 프로그램의 argument로 파일 이름을 넘겨받아 사용하게 되는데, 이것은 아주 간단하다. 다음은 argument로 넘겨진 모든 파일을 열어서 한 줄씩 입력을 받아서 출력하는 예이다.
while (<>) { print; }
이 코드는 다음과 동일한 의미를 가진다.
@ARGV = ('-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV) or warn "Can't open $ARGV: $!n"; while () { print; } }
argument로 넘겨받는 파일이름에 대해서는 신경쓸 필요 없이 <>만 사용하면 각 파일에 대해서 open하고 읽어들이는 과정이 모두 자동적으로 실행되는 것이다.
b) 출력
print연산을 사용하는 경우에는 default로 출력의 방향이 STDOUT으로 정해진다. 그러므로 다음의 세 문장은 같은 의미를 가진다.
print "Hello worldn"; print STDOUT "Hello worldn"; print STDOUT Hello, " ", world, "n";
STDOUT뒤에 ,를 찍지 않도록 주의하자. STDOUT은 출력 대상이 아니라 출력의 방향이기 때문이다.
특정 파일에 대해서 출력을 하기 위해서는 미리 쓰기 mode로 open을 해야 하고 그 이후에 print 연산에 출력 방향으로 그 파일의 filehandle을 지정하면 된다.
open(OUTPUT, "> output.log"); print OUTPUT "Result : All men are alive.n");
shell에서 사용하던 방식의 token을 이용한 출력방법도 있다. 이것을 here document 문법이라고 하며 token을 일종의 quote로 생각하는 것이다. 여러 줄에 걸쳐진 출력에 대해서 문서를 쓰듯이 출력할 수 있다는 게 장점이다.
print OUTPUT << EOF But most of payload are lost. Estimation of loss are still being carried. EOF
print 연산자는 EOF라는 토큰을 quote로 간주하고 두개 사이의 텍스트를 지정된 출력방향으로 내보내게 된다. 토큰에 따라서 보다 정교한 출력 방법이 있는데, 여기서는 몇 가지만 더 살펴보기로 하겠다.
print << "" x 10 Hello, world!
이 예제는 quote가 null string이므로(그러므로 ""조차 생략 가능하다.) 다음 줄만을 출력 대상으로 삼게 되고 print 연산을 10번 수행하게 된다.
print << `ANYTOKEN` id echo hello ANYTOKEN
token을 감싸는 것이 back-quote(backtick)임에 유의하라. back-quote는 명령을 실행시켜주는 역할을 한다. 그러므로 두 토큰 사이에 존재하는 id와 echo hello라는 명령이 실행된 결과가 출력되게 된다.
c) 에러 출력
에러는 파일로 보낼 수도 있지만, STDERR로 모아서 보내는 것이 일반적이다. 그러므로 print의 출력방향을 STDERR로 명시하면 된다.
print STDERR "Can't find such a file!n";
4) 비교 연산자
Perl에서는 문자열에서 사용되는 논리연산자와 수치에서 사용되는 논리연산자가 따로 제공된다. 다음의 표를 참조하라.
비교 표현식 | 수치연산자 | 문자열연산자 |
같은가? | == | eq |
같지 않은가? | != | neq |
보다 작은가? | < | lt |
보다 큰가? | > | gt |
같거나 작은가? | <= | le |
같거나 큰가? | >= | ge |
같지 않은가? | <=> | cmp |
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
1191 | [ 一日30分 인생승리의 학습법] REST, REST API, RESTful 과 HATEOAS | 졸리운_곰 | 2024.03.10 | 7 |
1190 | [ 一日30分 인생승리의 학습법] 렌더링 삼형제 CSR, SSR, SSG 이해하기 | 졸리운_곰 | 2024.03.10 | 1 |
1189 | [ 一日30分 인생승리의 학습법] 엑셀 VBA에서 셀레니움 사용을 위한 Selenium Basic 설치 | 졸리운_곰 | 2024.02.23 | 9 |
1188 | [ 一日30分 인생승리의 학습법]500 Lines or Less Blockcode: A Visual Programming Toolkit : 500줄 이하의 블록코드: 시각적 프로그래밍 툴킷 | 졸리운_곰 | 2024.02.12 | 3 |
1187 | [ 一日30分 인생승리의 학습법] 구글 클라이언트(앱) 아이디를 발급받으려면 어떻게 해야 하나요? | 졸리운_곰 | 2024.01.28 | 2 |
1186 | [ 一日30分 인생승리의 학습법] 빅뱅 프로젝트를 성공적으로 오픈하기 위한 팁 | 졸리운_곰 | 2023.12.27 | 14 |
1185 | [ 一日30分 인생승리의 학습법]“빅뱅 전환보다 단계적 전환 방식이 이상적 애자일팀과 협업 쉽게 체질 개선을” | 졸리운_곰 | 2023.12.27 | 6 |
1184 | [ 一日30分 인생승리의 학습법] Big-bang / phased 접근 | 졸리운_곰 | 2023.12.27 | 2 |
1183 | [ 一日30分 인생승리의 학습법] CodeDragon 메뉴 데이터 전환의 개념 이해 - 데이터 전환의 개념, 데이터 전환방식, 데이터 전환방식 및 장단점 비교, 데이터전환 이후 검토해야 할 사항 | 졸리운_곰 | 2023.12.27 | 4 |
1182 | [ 一日30分 인생승리의 학습법] 블록체인과 IPFS를 이용한 안전한 데이터 공유 플랫폼 - 분쟁 해결 시스템 | 졸리운_곰 | 2023.12.27 | 5 |
1181 | [ 一日30分 인생승리의 학습법] 블록체인과 IPFS를 이용한 안전한 데이터 공유 플랫폼 - 개념과 리뷰 시스템 | 졸리운_곰 | 2023.12.27 | 3 |
1180 | [ 一日30分 인생승리의 학습법] 소켓 CLOSE_WAIT 발생 현상 및 처리 방안 | 졸리운_곰 | 2023.12.03 | 6 |
1179 | [ 一日30分 인생승리의 학습법] robots 설정하기 | 졸리운_곰 | 2023.12.03 | 2 |
1178 | [ 一日30分 인생승리의 학습법] A Tutorial and Elementary Trajectory Model for the Differential Steering System of Robot Wheel Actuators : 로봇 휠 액츄에이터의 차동 조향 시스템에 대한 튜토리얼 및 기본 궤적 모델 | 졸리운_곰 | 2023.11.29 | 5 |
1177 | [ 一日30分 인생승리의 학습법] Streamline Your MLOps Journey with CodeProject.AI Server : CodeProject.AI 서버로 MLOps 여정을 간소화하세요 | 졸리운_곰 | 2023.11.25 | 1 |
1176 | [ 一日30分 인생승리의 학습법] Comparing Self-Hosted AI Servers: A Guide for Developers / : 자체 호스팅 AI 서버 비교: 개발자를 위한 가이드 | 졸리운_곰 | 2023.11.25 | 8 |
1175 | [ 一日30分 인생승리의 학습법] Self-Hosted Artificial Intelligence: Keeping Control of Your Data : 자체 호스팅 인공 지능: 데이터 제어 유지 | 졸리운_곰 | 2023.11.25 | 5 |
1174 | [ 一日30分 인생승리의 학습법] AI_머신러닝 기초 정리 | 졸리운_곰 | 2023.11.24 | 14 |
1173 | [ 一日30分 인생승리의 학습법] 머신러닝 내용 요약 및 정리 | 졸리운_곰 | 2023.11.24 | 9 |
1172 | [ 一日30分 인생승리의 학습법] 당신이 알아두어야 할 10가지 머신러닝 알고리즘 | 졸리운_곰 | 2023.11.24 | 7 |