Beginner's Introduction to Perl

______________________________________________________________________________

By Doug Sheppard on October 16, 2000 12:00 AM

Doug Sheppard가 2000년에 연재한 'Beginner's Introduction to Perl' 내용입니다.
펄 버전이 업데이트 됨에 따라 해당 내용이 꽤 업데이트 되었지만
여기에서는 업데이트 버전이 아닌 처음에 작성한 내용으로 소개합니다.



Perl의 세계에 온 것을 환영합니다.

Perl은 스크립팅 언어의 Swiss Army chainsaw(스위스 군용 전기 톱)이라고 합니다: 강력하고 이식성이 뛰어나기 때문입니다. Perl은 1980년대 후반 NASA에서 시스템 관리자로 일하던 언어학자인 Larry Wall에 의해, 보고서 처리를 보다 쉽게 하기 위해, 처음 개발되었습니다. 그 이후로 Perl은 아주 많은 역할을 하게 되었습니다: 다른 컴퓨터 시스템들 사이를 연결하여 시스템 관리를 자동화할 뿐만 아니라, 물론 웹 상에서 CGI 프로그래밍에 대해 가장 인기있는 언어의 하나가 되었습니다.


왜 Perl이 Web과 함께하며 그렇게 인기있게 되었을까요? 거기엔 2가지 이유가 있습니다: 첫째로 웹 상에서 수행되는 대부분의 것들은 text 형태로 일어나고, text 처리를 위해 고안된 언어에서 가장 잘 수행되기 때문입니다. 보다 중요하게, Perl은 사람들이 이용할 어떤 것이 필요할 때 다른 선택사항들보다 눈에 띄게 좋았습니다. C는 복잡하고 보안 문제를 일으킬 수 있었고 (특히 신뢰되지 않는 데이터일 경우), Tcl은 불편할 수 있고 Python은 정말 기반이 없었습니다.

또한 Perl은 사용하기 쉬운 친절한 언어이기 때문에 당신을 고통스럽게 하지는 않습니다. 당신의 개인적인 프로그래밍 스타일과 잘 어울릴 것입니다. Perl의 슬로건은 "그것을 하는데 하나 이상의 방법이 있다," 이며, 크고 작은 문제 모두 똑같이 유용할 것입니다.


연재의 첫번 째 부분에서, Perl에 대한 몇 가지 기본 사항을 배우고, 작은 샘플 프로그램을 볼 수 있습니다.

- Operating System에 대해

이 연재에서, Unix 시스템을 사용하고 Perl interpreter가 /usr/local/bin/perl에 위치하고 있다고 가정하겠습니다.
Windows를 구동해도 괜찮습니다: 대부분의 Perl 코드는 플랫폼과 무관합니다.


- 첫번째 Perl Program


아래 텍스트 내용으로 first.pl을 만드십시오:

#!/usr/local/bin/perl
print "Hi there!\n";


(전통적으로, 첫 프로그램은 Hello world! 라고 말하는게 일반적입니다^^)


이제, Perl 인터프리터로 실행하세요. 커맨드 라인에서, 파일이 있는 디렉토리로 가서 perl first.pl을 실행하면 아래와 같이 보게 될 것입니다.

Hi there!


\n은 newline 문자를 나타냅니다: 그것이 없다면, Perl은 스스로 텍스트의 new line으로 넘어갈 수 없습니다.


- 함수와 문장 (Functions and Statements)

Perl은 많은 함수 라이브러리를 갖고 있습니다. 그들은 인터프리터가 수행하는 명령들, Perl의 동사들입니다. perlfunc man 페이지에서 모든 내장 함수들의 목록을 확인할 수 있습니다. 거의 모든 함수들은 일련의 파라미터를 받을 수 있고, 그것들은 컴마에 의해 구분이 됩니다.

print 함수는 Perl의 가장 자주 사용되는 부분 중의 하나입니다. 스크린에 표시하거나 또는 파일에 정보를 보내기 위해 사용합니다. print 함수는 출력하기 위한 일련의 것들을 그것의 파라미터로서 가집니다.

print "This is a single statement.";
print "Look, ", "a ", "list!";


Perl 프로그램은 세미콜론으로 끝나는 문장들로 이루어져 있습니다. 문장들은 분리된 라인들일 필요는 없습니다; 하나의 줄에 다수의 문장들이 있거나 하나의 문장이 다수의 라인들에 분리되어 있을 수도 있습니다.


print "This is "; print "two statements.\n"; print "But this ",

"is only one statement.\n";

- 숫자, 문자열, 쌍따옴표 (Numbers, Strings and Quotes)

Perl에는 2개의 기본적인 데이터 형태가 있습니다: 숫자와 문자열

숫자는 쉽습니다; 우리는 그것들을 모두 다뤄왔습니다. 알아야 하는 것은 Perl에서 숫자 속에 컴마(,)나 스페이스를 넣으면 안된다는 것입니다. 10,000 또는 10 000이 아닌 10000이라고 항상 쓰세요.

문자열들은 보다 조금 복잡합니다. 문자열은 작은 따옴표 또는 큰 따옴표에 있는 문자들의 집합입니다:

'This is a test.'
"Hi there!\n"


작은 따옴표와 큰 따옴표의 차이는 큰 따옴표는 그 내용이 해석되어야(interpreted) 하는 것을 의미하는 반면, 작은 따옴표는 그 내용이 문자 그대로 받아들여져야 하는 것을 의미합니다.
예를 들면, 문자 시퀀스 \n은 큰 따옴표를 가진 문자열에서 나타나면 newline 문자이지만,
작은 따옴표에서 나타나면 문자 그대로 2개의 문자, 백슬래쉬와 n입니다.

print "This string\nshows up on two lines.";
print 'This string \n shows up on only one.';

(2개의 유용한 백슬래쉬 시퀀스는 탭 문자를 입력하는 \t 와, 큰 따옴표 안에 백슬래쉬를 입력하기 위한 \\입니다.)


- 변수(Variables)

함수들이 Perl의 동사라면, 변수들은 명사입니다. Perl은 3개 형식의 변수를 가지고 있습니다: 스칼라, 배열, 해쉬. 그것들을 "물건" "목록", "사전"이라고 생각하세요. Perl에서 모든 변수 이름들은 문자 또는 밑줄(_), 그리고 하나 이상의 영숫자 문자이거나 또는 밑줄들로 된 구두점 문자이다.

스칼라는 하나의 것들입니다. 숫자 또는 문자열일 수 있습니다. $abacus처럼 스칼라의 이름은 $ 표시로 시작합니다. 다음과 같이 = 기호를 사용하여 스칼라에 값을 할당할 수 있습니다:

$i = 5;
$pie_flavor = 'apple';
$constitution1776 = "We the People, etc.";


스칼라가 숫자인지 문자열인지 지정할 필요가 없습니다. Perl이 문자열로 처리해야 할 필요가 있을 때 그렇게 하고; 숫자로 처리해야 할 필요가 있을 때 그렇게 하기 때문에 문제가 되지 않습니다. 변환은 자동으로 일어납니다. (이것은 문자열들과 숫자들이 구별되는 데이터 형식인 다른 많은 언어들과는 다릅니다.)

큰 따옴표 문자열을 사용하는 경우, Perl은 문자열에 당신이 이름지은 스칼라 변수들의 값을 삽입할 것입니다. 이것은 문자열을 직접 채우는데 자주 사용한다:


$apple_count = 5;
$count_report = "There are $apple_count apples.";
print "The report is: $count_report\n";


이 코드의 마지막 출력은 The report is: There are 5 apples 입니다.

Perl의 숫자는 일반적인 수학적 연산으로 조작할 수 있습니다: 덧셈, 곱셈, 나눗셈과 뺄셈. (곱하기와 나누기는 Perl에서 *와 / 로 표시됩니다.)


$a = 5;
$b = $a + 10; # $b is now equal to 15.
$c = $b * 10; # $c is now equal to 150.
$a = $a - 1; # $a is now 4, and algebra teachers are cringing.


또한 ++, --, +=, -=, /=, *= 같은 특수 연산자를 사용할 수 있습니다. 이것들은 방정식의 2가지 요소를 필요로 하지 않고 스칼라의 값을 조작할 수 있습니다. 어떤 이들은 그것들을 좋아하고, 어떤 이들은 좋아하지 않습니다. 저는 그것들이 코드를 보다 명확하게 만들 수 있다는 사실을 좋아합니다.


$a = 5;
$a++; # $a is now 6; we added 1 to it.
$a += 10; # Now it's 16; we added 10.
$a /= 2; # And divided it by 2, so it's 8.


Perl의 문자열은 많은 유연성을 가지고 있지는 않습니다. 문자열에서 사용할 수 있는 유일한 기본 연산자는, "함께 합치다"고 말하는, 연결입니다. 연결 연산자는 마침표입니다. 연결과 더하기는 별개의 것입니다.


$a = "8"; # Note the quotes. $a is a string.
$b = $a + "1"; # "1" is a string too.
$c = $a . "1"; # But $b and $c have different values!


Perl은 필요할 때 숫자를 문자열로 변환한다는 것을 기억하세요, $b의 값을 얻기 위해서 Perl 인터프리터는 2개의 문자열 "8"과 "1"을 숫자로 변환하고, 그것들을 더합니다.
$b의 값은 숫자 9입니다. 하지만, $c는 연결을 사용했기 때문에, 그것의 값은 문자열 "81"입니다.

+ 표시는 숫자를 더하고 마침표(.)는 문자열들을 함께 합진다는 것을 꼭 기억하세요.

배열은 스칼라의 나열입니다. 배열 이름은 @로 시작합니다. 컴마(,)로 구분지어, 괄호() 안에 내용들을 나열함으로서 배열을 정의할 수 있습니다:


@lotto_numbers = (1, 2, 3, 4, 5, 6); # Hey, it could happen.
@months = ("July", "August", "September");


배열의 내용들은 0부터 시작하여 인덱싱됩니다. 배열의 요소들을 검색하려면, @ 표시를 $ 표시로 바꾸어야 합니다, 그리고 원하는 요소의 인덱스 위치를 가지고 따르면 됩니다. (스칼라 값을 얻는 것이기 때문에 $표시로 시작합니다.). 또한 다른 스칼라처럼, 위치에 있는 값을 수정할 수도 있습니다.


@months = ("July", "August", "September");
print $months[0]; # This prints "July".
$months[2] = "Smarch"; # We just renamed September!


그런데, 만일 배열이 존재하지 않을 경우, 그것의 요소중 하나에 값을 할당하려고 할 때 그 배열이 생성될 것입니다.


$winter_months[0] = "December"; # This implicitly creates @winter_months.


배열들은 같은 순서로 그것의 내용을 반환합니다; @months를 처음부터 끝까지 조사하면, 몇 번을 하더라도, July, August, September 순서대로 돌려받을 것입니다. 배열의 길이를 찾아내고 싶다면 $#array_name 값을 이용하세요. 이 값은 배열의 요소의 숫자보다 하나 작은 값입니다. 만일 그저 배열이 존재하지 않거나 비어있다면, $#array_name은 -1 입니다. 만일 배열의 크기를 조정하고 싶다면 그저 $#array_name의 값을 조정하면 됩니다.


@months = ("July", "August", "September");
print $#months; # This prints 2.
$a1 = $#autumn_months; # We don't have an @autumn_months, so this is -1.
$#months = 0; # Now @months only contains "July".


해시는 몇몇 프로그래밍 언어에서는 "사전"이라고 불립니다, 그리고 그들은 용어와 정의, 또는 보다 정확한 말로 키와 값입니다. 해시에서 각 키는 하나의 유일한 매치되는 값을 갖고 있습니다. %parents처럼 해시의 이름은 %표시로 시작합니다. 다음과 같이 컴마로 구분된 키와 값의 쌍에 의해 해시를 정의할 수 있습니다:


%days_in_summer = ( "July" => 31, "August" => 31, "September" => 30 );


$hashname{key}로 표현함으로서 해시로부터 어떤 값을 가져올 수 있습니다, 또는 어떤 다른 스칼라처럼 위치에 있는 값을 수정할 수 있습니다.


print $days_in_summer{"September"}; # 30, of course.
$days_in_summer{"February"} = 29; # It's a leap year.


해시에 어떤 키들이 존재하는지 확인하려면, 해시의 이름을 가진 keys 함수를 사용할 수 있습니다. 이것은 해시의 모든 키들을 포함하는 목록을 반환합니다. 그렇지만 목록은 항상 동일한 순서는 아닙니다; @months에서는 항상 July, August, September 순서라고 믿을 수 있는 반면, keys %days_in_summer는 어떤 순서로든 반환될 수 있다.


@month_list = keys %days_in_summer;
# @month_list is now ('July', 'September', 'August') !


변수의 3가지 형식은 3개의 구분되는 이름공간을 갖고 있습니다. 이것은 $abacus와 @abacus가 별개의 변수이고, $abacus[0] (@abacus의 첫번째 요소)는 $abacus{0} (키 0을 가지는 abacus에서의 값)과 같지 않음을 의미합니다.

- 주석(Comments)

앞부분에서 몇 개의 코드 샘플들에서 주석을 사용하였습니다. 이것들은 특별한 코드 조각들이 무엇을 하는지를 설명하는데 유용하며, 당신이 변경, 개선, 수정, 혹은 다시 확인하고자 하는 코드 조각들에 필수적입니다.(즉, 주석은 모든 코드에 대해 필수적입니다.)

Perl 코드 라인에서 # 표시 뒤에 오는 것들은 주석입니다. (물론, # 표시가 문자열에 나타나는 건 제외합니다.)


print "Hello world!\n"; # That's more like it.
# This entire line is a comment.


- 루프(Loops)

프로그램을 만들면 거의 매번, loop를 이용할 필요가 있습니다. 루프는 특별한 코드 조각이 반복적으로 실행되도록 합니다. 이것은 flow control이라 불리는 프로그래밍에서 일반적인 개념의 한 부분입니다.

Perl은 가장 기본적인 용도의, flow control에 유용한 몇 개의 다른 함수들을 가지고 있습니다. for 함수를 사용하는 경우, loop 인덱스로 사용될 변수, 그리고 반복할 일련의 값들을 지정해야 합니다. 중괄호 한 쌍 안쪽에, 루프 동안 실행하고자 하는 어떠한 코드를 넣으면 됩니다:

for $i (1, 2, 3, 4, 5) {
print "$i\n";
}


이 루프는 별도의 라인에 숫자 1부터 5까지를 출력합니다.


루프를 정의하는 것에 대해 편리한 단축키는 범위의 숫자들을 지정하기 위해 .. 를 사용하는 것입니다. (1, 2, 3, 4, 5)를 (1 .. 5)로 쓸 수 있습니다. 또한 루프 목록에서 배열들과 스칼라들을 사용할 수도 있습니다. 아래 코드를 시험해보고 무엇이 일어나는지 보세요:


@one_to_ten = (1 .. 10);
$top_limit = 25;
for $i (@one_to_ten, 15, 20 .. $top_limit) {
print "$i\n";
}


루프 목록에 있는 항목들이 숫자일 필요는 없습니다; 간단하게 문자열들을 사용할 수 있습니다.
만일 %month_has라는 해시가 달의 이름들과 각 달의 날짜 수를 포함하고 있다면, 그들을 단계적으로 거치기 위해 keys 함수를 사용할 수 있습니다.


for $i (keys %month_has) {
print "$i has $month_has{$i} days.\n";
}

for $marx ('Groucho', 'Harpo', 'Zeppo', 'Karl') {
print "$marx is my favorite Marx brother.\n";
}

- The Miracle of Compound Interest (복리의 기적)

작고 유용한 프로그램을 작성할 만큼 이제 Perl에 대해 많은 것을 배웠습니다. - 변수, print, 그리고 for() 등..
누구나 돈을 좋아합니다, 그래서 첫 샘플 프로그램을 복리 계산기로 했습니다.


#!/usr/local/bin/perl

# compound_interest.pl - the miracle of compound interest

# First, we'll set up the variables we want to use.
$nest_egg = 10000;   # $nest_egg is our starting amount
$year = 2000;        # This is the starting year for our table.
$duration = 10;      # How many years are we saving up?
$apr = 9.5;          # This is our annual percentage rate.

# Print the headers for our report.
print "Year", "\t", "Balance", "\t", "Interest", "\t", "New balance", "\n";

# Calculate interest for each year.
for $i (1 .. $duration) {
    print $year, "\t";
    $year++;

    print $nest_egg, "\t";

    # Try using this instead to see why this line looks so complex:
    # $interest = ($apr / 100) * $nest_egg
    $interest = int (($apr / 100) * $nest_egg * 100) / 100;
    print $interest, "\t";

    $nest_egg += $interest;

    print $nest_egg, "\n";
}

print $year, "\t", $nest_egg, "\n";





프로그램에서 가장 복잡한 단일 라인은 이것입니다:

$interest = int (($apr / 100) * $nest_egg * 100) / 100;

$apr / 100 은 이자율이고, ($apr / 100) * $mest_egg는 1년에 버는 이자의 양입니다. 이 라인은 int() 함수를 사용하는데, 그것은 스칼라의 integer 값을 반환합니다.(뒤에 붙는 소수 부분은 제거됩니다) 예를 들어, 9.25%로 10925를 곱할 때 결과는 1010.5625인데, 1010.56으로 반올림 처리를 해야만 하기 때문에 여기에서 int() 함수를 사용합니다. 이렇게 하기 위해 100으로 곱해 101056.25를 산출, int()를 사용하여 나머지 소수부분을 버려 101056을 산출, 그런 다음 다시 100으로 나누어, 최종 결과는 1010.56 입니다.



Play Around!

At this point you have some basic knowledge of Perl syntax and a few simple toys to play with - print, for(), keys(), and int(). Try writing some simple programs with them. Here are two suggestions, one simple and the other a little more complex:

· A word frequency counter. How often does each word show up in an array of words? Print out a report. (Hint: Use a hash to count of the number of appearances of each word.)

· Given a month and the day of the week that's the first of that month, print a calendar for the month. (Remember, you need \n to go to a new line.)