1580, 5/79 회원가입  로그인  
   asdzxc301
   펄1

http://www.hackerschool.org/HS_Boards/zboard.php?id=Free_Lectures&no=1149 [복사]


시작하기
Perl(펄이라고 읽는다: 역자)은 배우기 쉽고 사용하기 편한 언어다. Perl을 쉬운 언어라고 말하는 이유 중의 하나는 바로 Perl에서는 프로그래머가 표현하고 싶은 것을 서술하기 이전에 많은 것을 선언할 필요가 없다는 점이다.
다른 대부분의 프로그래밍 언어에서는 실제로 실행되는 프로그램의 첫 문장을 기술하기 전에 데이터 타입이나 변수, 서브루틴(subroutine) 등을 미리 선언해야 한다. 이런 점들은 복잡한 데이터 구조를 필요로 하는 어려운 문제들을 해결하는 데에는 도움이 될 지 모른다. 이런 점들은 복잡한 데이터 구조를 필요로 하는 어려운 문제들을 해결하는 데에는 도움이 될 지 모른다. 그러나 매일 부딪히게 되는 간단한 문제들을 해결하는 데에는 다음과 같이 간단히 기술할 수 있는 프로그래밍 언어를 사용하는 것이 훨씬 나을 것이다.
print "Howdy, world!\n";
Perl이 바로 그러한 언어이다. 실제로 위의 예제는 하나의 완벽한 프로그램이며, 이 예제 프로그램을 Perl 인터프리터로 실행하면 화면에 "Howdy, world!"라는 내용이 출력될 것이다.
또한 Perl에서는 프로그래머가 표현하고 싶은 것을 서술한 다음에 더 많은 것을 기술할 필요는 없다. 대부분의 다른 프로그래밍 언어와 달리, Perl에서는 프로그램의 끝까지 순서대로 실행하는 것이 프로그램의 실행을 마치는 일반적인 방법이다.
물론 프로그래머의 필요에 따라서 원하는 경우에는 exit 함수를 사용하여 명확하게 프로그램의 종료를 나타낼 수도 있고, 실제로 변수나 서브루틴을 사용하기 이전에 미리 명확하게 선언해 둘 수도 있으며, 미리 선언해야만 하도록 지정할 수도 있다. 그러나 이 모든 것은 프로그래머의 선택에 달린 것이다. Perl에서는 사용자의 자유가 최대한 보장되어 있다.
이밖에도 왜 Perl이 배우고 사용하기 쉬운 언어인지에 관한 여러 가지 이유가 있지만 지금 그러한 이유들을 일일이 나열할 필요는 없을 것 같다. 이 책을 읽으면서 자연스럽게 그 이유에 대해 알 수 있기 때문이다. 물론 보다 깊이 들여다 보면 어려운 점이 있을 수 있겠지만, Perl은 그러한 문제들을 최소한의 노력으로 해결할 수 있도록 도와줄 것이다. 이 점이 바로 다른 언어와 달리 Perl 프로그래머가 얼굴에 미소를 잃지 않고 프로그램을 작성할 수 있도록 하는 까닭이다.
이 장에서는 Perl의 개요에 대해 다룬다. 따라서 Perl에 관해 완벽하게, 그리고 논리적으로 다루지는 않을 것이다. 이 장에서는 마치 코끼리 다리를 만지는 시각 장애인에게 Perl에 관한 명확한 그림을 전달한다는 기분으로 Perl의 다양한 면을 보여줄 것이다.



자연어와 인공 언어
언어란 인간이 인간을 위해 만든 것이다. 그러나 오늘날과 같은 컴퓨터 시대에서는 이러한 사실이 때때로 잊혀질 때가 있다. Perl은 마치 자연어로 의사소통을 원활하게 하는 것과 비슷하게 동작하도록 만들어졌다. 언어학적인 측면에서 여러 가지 원리를 열거할 수도 있겠으나, 여기서 말하고 싶은 것은 언어를 디자인할 때 가장 중요한 점은, 쉬운 것은 쉬워야 하면서 동시에 어려운 것도 표현이 가능해야 한다는 것이다. 어떻게 보면 당연하게 보이는 이것이 실제로 많은 컴퓨터 언어에서 지켜지지 않고 있는 것이 오늘의 현실이다.
이러한 점에서 보면 자연어는 훌륭하다고 할 수 있다. 즉, 사람들은 자연어를 이용해 단순한 것과 복잡한 것을 끊임없이 전달하려 하고 있으며, 그 결과 언어는 단순한 것과 복잡한 것을 모두 표현할 수 있도록 진화해 나가고 있다. Perl도 자연 언어와 마찬가지로 진화해 나갈 수 있도록 고안되었으며, 실제로 진화해 가고 있다. 실제로 수 년에 걸쳐서 많은 사람들이 Perl의 진화에 공헌해 왔다.
누군가 “언어학”이라는 단어를 말했을 때 사람들은 단어 혹은 문장, 둘 중의 하나를 생각할 것이다. 그러나 이러한 단어나 문장이라는 것도 결국은 말(다시 말해 언어)을 나누기 위한 방법에 불과하다. 이러한 단어나 문장도 다시 의미를 갖고 있는 더 작은 단위로 쪼개어지든지, 혹은 여러 개가 모여서 의미를 갖는 더 큰 단위를 이루기도 한다.  
자연어에서는 명사, 동사 따위의 다양한 단어가 존재한다. 단어 하나를 말했을 때 그것이 명사일 지라도 문장 내부에서의 위치나 쓰임새에 따라서 동사로, 형용사로 또는 부사로도 사용될 수 있는 것이다.
자연어와 마찬가지로 Perl에서도 어떤 단어는 그 단어가 놓여진 위치에 따라서 다양한 방식으로 해석되고 동작한다. 다만 Perl은 프로그래머가 지금 무엇을 표현하고 싶은지를 이해하기 위해 최대한 노력한다는 점을 명심해 주기 바란다. 대부분의 경우 어떻게 표현하더라도 Perl은 이해하고 받아들인다.(물론 말도 안되게 작성한 경우는 제외되겠지만 Perl 해석기(parser)는 영어나 스와힐리어보다는 Perl을 더 잘 이해하기 때문이다)
명사를 생각해 보자. 명사는 특정한 객체(object)의 이름일 수도 있고, 현재 참조되고 있는 사실을 명확하게 보여주지는 않지만 어느 객체 클래스의 이름을 나타낼 수도 있다. 대부분의 컴퓨터 언어에서는 이러한 구분을 뚜렷이 하기 때문에 특정한 무엇을 말할 때는 값(value)이라고 하고, 일반적인 무엇을 말할 때는 변수(variable)라고 한다.
값이란 어떤 곳에 존재하고, 그 값이 어디에 있는지를 알고 있는 것임에 비해, 변수는 그 변수가 존재하는 동안에 하나 혹은 그 이상의 여러 가지 값을 가질 수 있다는 것을 말한다. 따라서 어떤 변수를 해석하기 위해서는 프로그램의 진행에 따른 변수 값의 변화를 추적해야만 한다. 이러한 해석은 여러분의 두뇌에서나 혹은 컴퓨터가 하게 될 것이다.


명사
변수란 어떤 값을 저장할 수 있는 이름을 가지는 장소로, 이러한 변수를 이용하여 특정한 값을 저장한 다음 나중에 참조할 수 있다. 실제로 일상 생활에서도 개인적으로 또는 공공을 위한 목적으로 다양한 종류의 보관 장소들을 찾아볼 수 있다. 이런 장소들은 임시로 사용되기도 하지만 영구적으로 이용될 수 있는 곳도 있다.
전산학에서는 흔히 변수의 범위(scope)에 관해 많이 언급하기도 한다. Perl에서는 이러한 변수의 범위에 관해 다양한 방법으로 접근하고 있으며 이러한 내용은 3장에서 자세히 다룰 것이다. (궁금한 분은 3장에서 "local"과 "my"에 관한 항목을 살펴보기 바란다.)
이러한 변수를 구분하는 데 더 유용한 방법은, 그 변수가 담고 있는 데이터의 종류를 기준으로 구분하는 것이다. 영어에서와 마찬가지로 Perl에서 가장 기본적인 구분은 단수 데이터와 복수 데이터이다. 문자열과 숫자는 단수 데이터에 속하며, 문자열이나 숫자의 리스트(list)는 복수 데이터이다. (객체지향 프로그래밍 부분에 도달하게 되면, 마치 어떤 한 학급의 학생들처럼 특정 객체가 밖에서는 단수 데이터로 보이지만 객체 내부에서는 복수로 보이는 예를 보게 될 것이다.)
이러한 단수 데이터를 스칼라(scalar)라고 부르며, 복수 데이터를 배열(array)이라 한다. 다음 예에서 문자열을 스칼라 변수에 저장하는 것을 살펴보도록 하자.
$phrase = "Howdy, world!\n";              # 변수를 지정.
print $phrase;                                # 변수의 내용을 출력.
위의 예에서 $phrase라는 변수를 미리 선언하지 않은 점을 유의해서 보아주기 바란다.  $는 Perl로 하여금 phrase가 스칼라 변수, 즉 단수 데이터를 포함하고 있는 것을 알게 해 준다. 이에 반해 배열은 @로 시작한다. 다음을 이해하면 기억하기 쉬울 것이다.  $는 스칼라(scalar)의 머리 글자 S를, @는 배열(array)의 머리 글자 a를 나타낸 것이다.
이 밖에도 Perl에는 해쉬(hash)나 핸들(handle), 타입글로브(typeglob) 등과 같은 데이터 타입이 존재하며, 스칼라나 배열과 마찬가지로 특정한 머리 글자를 통해 구분하게 된다. 다음 표에 데이터 타입을 구분하는 머리 글자를 정리해 두었다.
타 입머리 글자예설 명스칼라$$cents특정한 값(숫자나 문자열)배열@@large숫자 키를 가진 값의 리스트해쉬%%interest문자열 키를 가진 값의 리스트서브루틴&&howPerl의 실행 가능한 코드 일부분Typeglob**struckstruck이라고 이름 붙은 모든 것[표 1-1] 변수 표기법
단수성(Singularities)
앞의 예에서 보았듯이 Perl에서도 다른 대부분의 컴퓨터 언어에서와 마찬가지로 = 연산자를 이용해 스칼라 변수에 새로운 값을 대입한다. 스칼라 변수에는 정수, 실수, 문자열, 그리고 다른 변수나 객체를 가리키는 레퍼런스 등 다양한 형태의 값을 대입할 수 있다.
Perl에서는 유닉스(Unix) 쉘에서와 마찬가지로 다양한 방식으로 인용부호를 사용하여 여러 가지 타입의 값을 표현할 수 있다. 겹 따옴표(") 안에서는 변수 삽입(interpolation)과 역슬래쉬(\) 표현이 가능하고, 인용부호(') 안에서는 이들 모두의 변환이 이루어지지 않는다. 역 인용부호(`)는 따옴표로 둘러싸여 있는 외부 명령(혹은 프로그램)을 실행하도록 한 다음 그 반환값을 받을 수 있게 한다. 따라서 외부 명령의 실행 결과를 하나의 문자열로 받을 수 있다.
$answer = 42;                       # 정수
$pi = 3.14159265;                   # 실수
$avocados = 6.02e23;                # 지수 표현
$pet = "Camel";                     # 문자열
$sign = "I love my $pet";           # 변수 삽입된 문자열
$cost = 'It costs $100';           # 변수 삽입되지 않은 문자열
$thence = $whence;                  # 다른 변수의 대입
$x = $moles * $avocados;    # 표현식
$cwd = `pwd`;                       # 명령어 실행 후 그 결과를 문자열로 저장
$exit = system("vi $x");            # 명령어(system) 의 반환값을 저장
$fido = new Camel "Fido";           # 객체
특정한 값으로 초기화되지 않은 변수는 처음에 널(Null) 값("" 혹은 0)으로 지정되었다가, 나중에 사용되었을 때 해당 변수가 사용되는 위치나 대입되는 값에 따라서 문자열이나 숫자, 혹은 참, 거짓을 나타내는 불린(Boolean) 등과 같은 타입이 자동으로 결정된다. Perl에는 다양한 연산자가 존재하며 이들 연산자는 각각의 종류에 따라 특정한 형태의 값을 파라미터(매개변수)로 요구한다. Perl에서는 현재의 구문(context)에 맞도록 자동으로 데이터를 필요한 형태로 변환하는데, 아래의 예에서 살펴보기로 하자.
$camels = '123';
print $camels + 1, "\n";
위에서 첫째 줄에 의해 $camels는 문자열 변수로 자동 지정된다. 문자열 값인 '123'이 대입되었으므로. 둘째 줄에서 $camels는 숫자 1을 더하기 위해 자동으로 문자열에서 숫자 123으로 변환되어 124(123+1)의 숫자 값을 가진 후, 다시 문자열 '124'로 변환되어 화면에 출력된다. 줄바꿈을 나타내는 “\n"은 애초에 문자열이었기 때문에 출력하기 위해 더 이상의 변환은 이루어지지 않는다.  
여기서 주의할 점은 줄바꿈 기호를 나타낼 때 겹 따옴표를 사용하였다는 것이다. 만약 홑 따옴표를 사용하여 ‘\n'과 같이 나타낼 경우, 이것은 줄바꿈을 나타내는 것이 아니라 단순히 “\“와 “n“ 두 글자로 이루어진 문자열을 표현하는 것이다. 겹 따옴표와 홑 따옴표는 특정한 형태의 구문을 나타내기 위해 사용하며, 따옴표 안에서의 삽입, 치환은 둘 중에 어느 것을 사용했는지에 따라 다르게 나타난다.
복수성(Pluralities)
여러 개의 값을 한데 묶어서 한 번에 그 값을 저장할 필요가 있을 때가 있다. Perl에서는 이런 경우 두 가지 형태의 변수 타입을 제공한다. 배열(array)과 해쉬(hash)가 바로 그것이다. 많은 경우 이들은 스칼라와 비슷하게 취급된다. 배열이나 해쉬 변수에 어떤 값들을 대입하려면 대입식의 우측에 리스트 구문(list context)에 해당하는 것을 적어 주어야 한다.
어떤 값들을 숫자 인덱스에 의해 구분하고 싶을 경우에는 배열을 사용하고, 이름 인덱스에 의해 구분할 경우에는 해쉬를 사용한다. 이들 타입은 서로 상호 보완적이다.
배열 배열은 스칼라 값을 순서대로 나열한 리스트로서 리스트 내의 순서(index)에 따라 그 값을 참조할 수 있다. 배열의 요소로는 숫자나 문자열, 혹은 이 두 가지가 섞인 형태의 값이 올 수 있다. 사실 이들 외에도 배열의 요소에는 다른 리스트의 레퍼런스가 올 수도 있다. 이런 경우에 대해서는 4장에서 자세히 살펴보기로 하자. 배열에 리스트 값을 대입하려고 할 때에는 괄호를 사용하여 다음과 같이 나타낸다.
@home = ("couch", "chair", "table", "stove");
역으로 @home을 대입식의 우변에 위치하는 경우와 같이 리스트 구문에서 사용할 경우, 다음과 같이 할 수도 있다. 이 때 좌변에는 4개의 스칼라 값을 갖는 변수를 지정하면 된다.
($potato, $lift, $tennis, $pipe) = @home;
이것을 리스트 대입(list assignment)이라고 한다. 이러한 대입은 병렬로 진행되므로 다음과 같이 두 변수 값의 교환이 자연스럽게 이루어진다.
($alpha,$omega) = ($omega,$alpha);
C에서와 마찬가지로, 배열의 인덱스는 0에서부터 시작한다. 따라서 4개의 구성 요소를 갖고 있는 배열에서는 인덱스의 값이 0, 1, 2, 3이 된다. 배열에서 인덱스는 [ ] 기호 안에 위치하며, 배열의 특정한 요소를 참조하고 싶을 경우에는 $home[n]과 같이 배열의 이름과 인덱스를 동시에 지정해야 한다. 아래의 예를 참고하기 바란다. 배열의 구성 요소 자체는 스칼라 값이므로 이 경우 특정 요소를 나타낼 때 배열 이름 앞에 반드시 $ 를 붙여야 한다.
배열에 값을 대입할 때, 위의 예처럼 한꺼번에 하지 않고 한 번에 하나씩 대입하려면 다음과 같이 한다.
$home[0] = "couch";
$home[1] = "chair";
$home[2] = "table";
$home[3] = "stove";
배열은 그 요소의 순서가 정해져 있는 상태이므로, push, pop과 같은 스택 연산 등 다양한 연산자를 사용할 수 있다. 스택은 결국 입/출력 순서가 정해져 있는 리스트라고 할 수 있다. Perl에서는 리스트의 끝을 스택의 최상단(top)으로 간주한다.
해쉬 해쉬는 배열과는 달리 숫자로 된 인덱스가 아닌 임의의 스칼라 인덱스에 의해 참조되는, 순서가 정해져 있지 않은 스칼라 리스트이다. 이러한 이유로 흔히 해쉬를 일컬어 조합 배열(associative array)이라 부르기도 한다. 이것을 해쉬라고 이름 붙인 이유 중 하나로, 배열과 달리 요소의 순서가 정해져 있지 않다는 것이다.(Perl 내부에서 해쉬를 구현하기 위해서는 해쉬 표 참조(hash table lookup)라는 방법을 사용하고 있다.) 요소의 순서가 정해져 있지 않으므로, 앞서 말한 배열의 경우와 달리 해쉬에서는 push나 pop과 같은 스택 연산자를 사용할 수 없다. 해쉬에는 시작이나 끝을 알리는 값이 없다. 그럼에도 불구하고 해쉬는 매우 중요하며 상당히 유용한 것임에 틀림없다.
해쉬의 구성 요소를 참조할 때 사용되는 키(key) 값은 배열과 달리 그 구성 요소의 위치에 따라 자동으로 정해지는 것이 아니므로, 처음 해쉬를 지정할 때 해쉬 구성 요소의 값과 키 값을 같이 적어 주어야 한다. 물론 해쉬를 배열과 같은 방법으로 초기값을 지정할 수도 있지만, 그 값들이 모두 해쉬의 구성요소 값으로 들어가는 것이 아니라, 앞에서부터 순서대로 키/요소 값의 쌍으로 대입된다는 것을 명심하여야 할 것이다. 만약 3글자로 축약된 형태의 요일 명을 원래 요일 명으로 변환하도록 하기 위한 해쉬를 만드는 경우 아래 예와 같이 하면 된다.
%longday = ("Sun", "Sunday", "Mon", "Monday", "Tue", "Tuesday",
            "Wed", "Wednesday", "Thu", "Thursday", "Fri",
            "Friday", "Sat", "Saturday");
그러나 위와 같이 할 경우 키 값과 요소 값의 구분이 한 눈에 들어오지 않으므로, Perl 에서는 해쉬를 정의할 때 => 연산자를 이용하여 키와 그 값을 한 쌍으로 묶어 지정할 수 있도록 하고 있다.
%longday = (
    "Sun" => "Sunday",
    "Mon" => "Monday",
    "Tue" => "Tuesday",
    "Wed" => "Wednesday",
    "Thu" => "Thursday",
    "Fri" => "Friday",
    "Sat" => "Saturday",
);
앞서 배열에서와 마찬가지로, 해쉬 변수에 키/값의 리스트를 대입하는 것과 반대 방향으로 대입할 수도 있다. 해쉬는 keys 함수를 사용하여 해쉬의 키만 뽑아낼 수도 있으며, 뽑아낸 키를 sort 함수를 이용해 원하는 순서대로 나열할 수도 있다. 자세한 설명은 나중에 하기로 하자.
해쉬의 특정 요소를 참조하려면 해쉬의 키를 { }를 사용하여 배열의 인덱스처럼 참조하면 된다. 위의 예에서 Wed키에 해당하는 값을 참조하기 위해서는 $longday{Wed} 와 같이 하면 된다. 앞서 배열에서와 마찬가지로 해쉬의 특정 구성 요소의 값은 스칼라이므로 %가 아니라 $를 앞에 붙여야 한다는 것을 주의하여야 한다.


동사
일반적인 다른 컴퓨터 언어와 마찬가지로 Perl에서도 대부분의 동사에 해당하는 것은 명령어이다. 이들 명령어는 Perl로 하여금 특정한 무언가를 하도록 지시한다. 자연어에서 동사로 시작하는 문장이 명령문인 것과 마찬가지로 Perl에서도 동사로 시작되는 문장은 특정한 동작을 하도록 지시하는 문장이다. 가장 많이 볼 수 있는 예는 아래와 같은 print 명령어일 것이다.
print "Adam's wife is ", $wife{'Adam'}, ".\n";
위와 같이 특정한 작업을 지시하는 문장 외에도 Perl에는 다른 형태의 동사가 존재하며, 이들은 조건문에서 사용되거나 입력된 값을 다른 형태의 출력 값으로 변환하는 등의 일을 한다. Perl에서는 이러한 동사를 함수(function)라고 부른다.
Perl에서 미리 정의된(built-in) 함수의 예 중 하나는 다음과 같은 지수 함수이다.
$e = exp(1);                # 2.718281828459
Perl에서는 프로시져(procedure)와 함수를 뚜렷이 구분하고 있지는 않다. 필요에 따라서 이 두 가지 용어를 번갈아가면서 사용할 것이다. 또한 서브루틴이나 연산자(operator)등도 Perl에서의 동사에 속하는 것들이다. 이들을 무엇이라고 불러도 좋다. 이들은 모두 그 값이 의미가 있든지 없든지 어떤 값을 반환하며, 반환된 값을 사용하든 안하든 그것은 전적으로 프로그래머의 자유다.
앞으로 이 책에서는 Perl과 자연어의 닮은 점을 몇 가지 더 보게 될 것이다. 물론 자연어와 비교하는 것 외에도 Perl을 보는 또 다른 방법이 얼마든지 있을 수 있다. 더하기, 빼기, 지수함수와 같은 수학적인 문제 외에도, 제어나 프로토타입(prototype)을 만드는데, 텍스트나 리스트를 처리하는 언어로, 그리고 객체지향 언어 등 얼마든지 다른 쪽으로도 Perl을 사용할 수 있다.
그러나 Perl은 동시에 평범한 컴퓨터 언어의 하나이다. 앞으로 볼 예가 바로 그러한 것에 관한 내용이다.



성적처리 예제
한 학급의 성적을 처리하는 경우를 생각해 보도록 하자. 이 때 각 학생별 점수를 기록한 텍스트 파일을 grade라고 하고, 다음과 같은 형식으로 이루어져 있다고 하자.
Noel 25
Ben 76
Clementine 49
Norm 66
Chris 92
Doug 42
Carol 25
Ben 12
Clementine 0
Norm 66
...
이 경우 아래 스크립트를 이용하여 전체 학생의 총점, 각 학생의 평균을 구한 다음 학생 이름을 알파벳 순으로 출력할 수 있다. 이 프로그램에서는 같은 반에 동명이인이 없다고 가정한다. 즉, 같은 이름이 두 번 나오면 그것은 그 학생의 또 다른 점수라고 가정한다는 것이다.
아래 그림에서 BASIC 언어와 같은 행 번호는 편의상 붙인 것으로서 프로그램의 일부를 말하는 것은 아니다.
1  #!/usr/bin/perl
2
3  open(GRADES, "grades") or die "Can't open grades: $!\n";
4  while ($line = <GRADES>) {
5      ($student, $grade) = split(" ", $line);
6      $grades{$student} .= $grade . " ";
7  }
8
9  foreach $student (sort keys %grades) {
10      $scores = 0;
11      $total = 0;
12      @grades = split(" ", $grades{$student});
13      foreach $grade (@grades) {
14          $total += $grade;
15          $scores++;
16      }
17      $average = $total / $scores;
18      print "$student: $grades{$student}\tAverage: $average\n";
19  }
Perl에 대해 계속 알아보기 전에, 위의 예제 프로그램에서 나온 몇 가지에 대해 좀 더 자세히 알아보기로 하자. 만약 다른 주제에 관해 다루기를 원하는 사람은 다른 장으로 옮겨 가도 좋다.


어떻게 실행되나
여러분 중에는 Perl 프로그램을 어떻게 실행시켜야 할 지 모르는 사람도 있을 것이다.  그 방법은 다음과 같다. 즉, 여러분이 작성한 Perl 프로그램(혹은 스크립트)를 perl 인터프리터(대소문자 구분에 주의할 것)에 전달하여 실행하도록 하는 것이다. Perl의 슬로건은 다음과 같다.
어떤 일을 하는 데에는 여러 가지 방법이 있다. (There's More Than One Way To Do It)
Perl 인터프리터인 perl을 실행하는 방법 중 첫 번째 방법은 명령어 행에서 단순히 perl을 실행하는 것이다. 만약 UNIX 사용자인 경우 -e 스위치를 사용하여 다음과 같이 실행하면 된다.(아래 예에서 % 표시는 쉘 프롬프트를 나타낸 것으로 타이핑할 필요는 없다.)
% perl -e 'print "Hello, world!\n";'
UNIX 외의 다른 운영체제에서는 정확하게 위 문장과 같지 않을 수도 있다. 그러나 기본적인 원리는 모두 같다.
위의 예와 같은 한 줄짜리 간단한 것 보다 긴 스크립트의 경우, 일반적인 문서 편집기로 작성한 다음 파일로 저장하고 다음과 같이 실행하면 된다. (스크립트 파일의 이름이 gradation인 경우)
% perl gradation
물론 여전히 perl 인터프리터를 직접 호출하기는 했지만, 이 경우는 위의 예와는 달리 명령어 행에 Perl 문장을 적지 않고 프로그램을 실행할 수 있을 뿐 아니라, 특정 쉘(csh, ksh 등)에서 필요한 인용 부호 등에 관한 문제도 없게 된다.
스크립트를 실행하는 가장 편리한 방법은 스크립트를 직접 실행하고, 운영체제로 하여금 해당 스크립트에 필요한 인터프리터를 찾도록 하는 것이다. 몇몇 운영체제에서는 이러한 일련의 일을 파일의 확장자와 특정 응용 프로그램과의 연결, 혹은 특정 디렉토리와 응용 프로그램의 연결로 해결하기도 한다. 그러한 경우에는 사용자가 Perl 스크립트와 인터프리터를 연결해 주어야만 한다. UNIX 시스템에서는 스크립트의 첫 줄에 #!을 사용하여 해당 스크립트의 실행에 필요한 프로그램을 지정할 수 있도록 되어 있다. 앞서 성적 예제 프로그램의 첫 줄에서
% #!/usr/bin/perl
이라고 적어 놓았을 경우 스크립트를 실행하기 위해서는 단지
% gradation
이라고만 하면 된다. 물론 이 때 스크립트가 실행 가능한 모드(chmod(1) 참조)로 되어 있으며 PATH 안에 포함되어 있는지 확인하여야 한다. 만약 스크립트가 위치하고 있는 디렉토리가 PATH 환경 변수에 포함되어 있지 않다면 다음과 같이 디렉토리를 포함한 스크립트 명을 주어서 실행하도록 해야 한다.
% ../bin/gradation
만약 #! 표기를 지원하지 않는 오래된 UNIX 시스템이거나, perl 인터프리터를 나타내는 절대 경로가 32글자(많은 시스템에서 제한된 한계값)를 넘어서는 경우, 첫 번째 줄을 다음과 같이 하여 해결할 수 있다.
#!/bin/sh -- # perl, to stop looping
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
    if 0;
몇몇 운영체제에서는 /bin/csh이나 DCL, COMMAND.COM 등과 같은 기본 명령어 해석기에 따라 적절한 변형을 하여야 할 수 있을 것이다. 자세한 것은 주위의 전문가에게 물어보기 바란다.
이 책 전체에서는 앞으로 Perl 인터프리터의 위치를 #!/usr/bin/perl로 나타낼 것이다.  여러분은 각자의 시스템에 맞도록 적절히 변경하기 바란다.
주의사항 1: 만약 시험용 스크립트를 만들 경우, test라는 이름으로 만들지 말기 바란다. UNIX 시스템에는 미리 지정된 test라는 명령어가 있으며 스크립트를 실행할 경우 이 명령어가 실행될 수도 있다. test 대신 try를 사용하라.
주의사항 2: Perl을 처음에 공부할 때, 그리고 나중에라도 개발 중일 때는 perl을 실행할 때 -w 옵션을 사용하길 바란다. 이 옵션을 사용하면 스크립트 실행시 다양하고 유익한 각종 경고 메시지를 출력한다. 스크립트에서는 첫 줄에 다음과 같이 적으면 된다.
#!/usr/bin/perl -w
이제 여러분은 여러분 자신이 만든 Perl 프로그램(perl 인터프리터와 혼동하지 말 것) 을 어떻게 실행하는 지에 관해 배웠다. 그럼 앞서의 예제 프로그램으로 돌아가 보자.



파일 핸들
프로그램 내에서 외부와 어떤 데이터를 주고 받기 위해서는 몇 가지 방법이 있다. 그 중 하나가 앞서 예제 프로그램 3, 4번째 줄에 있는 GRADES와 같이 파일 핸들 이라는 Perl의 데이터 타입이다. 파일 핸들은 특정 파일이나 장치, 소켓, 혹은 파이프의 이름을 알기 쉽고 나중에 참조하기 쉽도록 이름 붙인 것으로서, 이러한 파일 핸들을 사용하게 되면 OS나 인터프리터 내부에서 벌어지는 버퍼링(buffering)등 복잡한 내용을 알고 있지 않아도 된다.(여기서의 파일 핸들은 C++에서의 스트림(stream)이나 BASIC의 I/O 채널과 비슷하다)
파일 핸들은 사용자로 하여금 다양한 곳으로 입/출력을 쉽게 할 수 있도록 해 준다. Perl을 glue 언어의 좋은 예로 드는 이유 중의 하나는 많은 파일이나 프로세스와의 연결을 이러한 파일 핸들을 통해 쉽게 할 수 있다는 데에 있다. 프로그램 외부의 다양한 객체에 잘 어울리는 이름을 붙여 사용할 수 있다는 것이 바로 좋은 glue 언어의 예라고 할 수 있다.
이러한 파일 핸들은 open 함수를 사용하여 생성, 파일에 쉽게 연결할 수 있다. open 함수는 두 개의 파라미터를 갖는데, 하나는 파일 핸들이고 다른 하나는 파일 핸들과 연결하려는 파일명이다. 이 밖에 Perl에는 미리 정의된(그리고 미리 열려 있는) 몇 개의 파일 핸들이 있다. STDIN은 프로그램의 기본 입력 채널, STDOUT은 기본 출력 채널, 그리고 STDERR은 기본 오류 출력 채널을 뜻한다.
open 함수를 사용하여 파일 핸들을 만들 때에는, 다양한 사용 용도(입력, 출력, 파이프)에 따라 다음과 같이 하면 된다.
open(SESAME, "filename");                        # 현재 파일로부터 읽기
open(SESAME, "<filename");                       # 위와 같음 (읽기를 명확하게 표시)
open(SESAME, ">filename");                       # 파일을 만들고 쓰기
open(SESAME, ">>filename");                      # 현재 파일 뒤에 덧붙여 쓰기
open(SESAME, "| output-pipe-command");        # 출력 필터 만들기
open(SESAME, "input-pipe-command |");            # 입력 필터 만들기
물론 파일 핸들의 이름은 사용자의 필요에 따라 임의로 지정할 수 있다. open 함수를 통해 일단 열려진 후에는, SESAME라는 파일 핸들은 close(SESAME) 함수를 통해 닫혀지거나 같은 파일 핸들 명으로 다른 파일에 연결되기 전까지 해당 파일이나 파이프를 참조하는 데 사용된다.
입력을 위해 파일 핸들을 만든 후에는(혹은 STDIN을 사용하는 경우), 줄 입력 연산자 < >을 사용하여 한 줄씩 읽어 들일 수 있다. 앵글 연산자 < >을 읽어 들일 파일 핸들 앞 뒤에 붙이면 된다.(예: <SESAME>) 따라서 STDIN 파일 핸들을 사용해 사용자로부터 입력을 받아 들이는 프로그램은 다음과 같이 될 것이다.
print STDOUT "Enter a number: ";                  # 숫자 입력을 요구
$number = <STDIN>;                               # 숫자 입력을 받음
print STDOUT "The number is $number\n";           # 숫자를 출력
위의 예에서는 STDOUT 표준 출력을 통해 출력 파일 핸들을 사용하는 예를 보였다.  print 함수의 첫 번째 파라미터로 파일 핸들이 올 수 있으며, 이 경우 print 함수의 출력은 해당 파일 핸들로 가게 된다. 위의 경우, 굳이 STDOUT을 지정하지 않더라도 표준 출력으로 print 함수 출력이 나가게 된다. STDIN이 기본 입력인 것과 같이 STDOUT 은 기본 출력에 해당한다.(앞서 성적 프로그램 예제의 18번째 줄에서는 이 같은 이유로 굳이 STDOUT을 지정하지 않았다.)
위의 예제에서 언급하지 않은 것이 또 하나 있다. 예제를 실행하게 되면 아마 빈 줄이 중간에 한 줄 들어가게 될 것이다. 이것은 표준 입력으로부터 값을 읽어 들일 때 자동으로 개행문자가 제거되지 않았기 때문이다.(예를 들어 입력이 "9\n" 과 같은 경우) 이런 경우 개행문자를 제거하려면 Perl에서 기본적으로 제공하는 chop이나 chomp함수를 사용하면 된다. chop 함수는 무조건 입력의 마지막 글자를 제거하는 데 비해, chomp는 레코드 종결 표시자(일반적으로 "\n" )로 지정된 글자를 제거한 다음 제거된 글자의 총 개수를 반환한다. 앞으로의 예제에서는 입력을 받아 들이는 다음과 같은 줄을 자주 보게 될 것이다.
chop($number = <STDIN>);        # 숫자 입력 후 줄바꿈 제거
위의 문장은 다음 두 문장을 합해 놓은 것과 같다.
$number = <STDIN>;                # 숫자 입력
chop($number);                        # 줄바꿈 제거



연산자
앞서 말한 대로, Perl은 또한 수학적인 언어이다. 이는 저수준(low level)의 비트 연산에서부터 숫자 및 집합 연산, 그리고 다양한 형태의 추상적 연산에 이르는 다양한 단계의 연산을 행할 수 있다는 것을 의미한다. 수학자들은 그들 나름대로의 각종 수학적 표기법을 만들어내어 사용하듯이, 전산학자도 이러한 수학적인 표기법을 만들어 내곤 한다. Perl에는 C나 FORTRAN, sed(1), awk(1) 등에서 빌려 온 다양한 연산자가 존재하며, 이들에 익숙한 사람들은 그리 낯설지 않을 것이다.
Perl에 기본적으로 포함되어 있는 다양한 연산자는 인수의 개수에 따라 1원(unary), 2원(binary), 3원(ternary) 연산자로 분류된다. 또한 이들 연산자는 그 위치에 따라 삽입(infix) 연산자 및 접두(prefix) 연산자로 분류되기도 하며, 연산이 행해지는 객체의 종류에 따라 분류되기도 한다. 나중에 이들 연산자 모두를 분류한 표를 보기 전에, 우선 몇 가지 기본적인 연산자에 대해 알아보자.


산술 연산자
산술 연산자는 더하기, 빼기 등 기본적인 산술연산을 행하는 연산자이다. 이들은 숫자에 대해 몇 가지 종류의 수학적인 기능을 행한다.
예이름결과$a + $b더하기$a와 $b의 합$a * $b곱하기$a와 $b의 곱$a % $b계수(modulus)$a를 $b로 나눈 나머지$a ** $b누승(exponentiation)$a의 $b승(표 1-2) 몇 가지 2원 산술 연산자
위에서 빼기(-)와 나누기(/) 연산자를 빠뜨렸지만, 이들이 어떻게 동작하는 지에 대해서는 위에 나타낸 연산자와 마찬가지로 여러분이 상상하는 그대로이다. 이들 산술 연산자는 수학 시간에 배운 대로 우선순위에 따라 연산이 행해지므로, 먼저 실행해야 할 연산에 대해서는 괄호를 사용하여 묶어 주어야 한다.


문자열 연산자
Perl의 문자열 연산자에도 "더하기" 연산자가 있는데, 두 개의 문자열을 잇는 문자열 연결 연산자(.)가 바로 그것이다. 다음 예를 보자.
$a = 123;
$b = 456;
print $a + $b;                # 579 출력
print $a . $b;                # 123456 출력
또한 문자열의 "곱하기" 연산자도 있는데, 이것을 반복(repeat) 연산자라고도 하며 산술 연산자의 곱하기와 구별하기 위해 "x"를 사용한다.
$a = 123;
$b = 3;
print $a * $b;                # 369 출력
print $a x $b;                # 123123123 출력
이러한 문자열 연산자는 비슷한 기능을 하는 산술 연산자와 같이 긴밀하게 연관되어 있다. 반복 연산자의 경우 왼쪽에는 문자열을, 오른쪽에는 숫자 파라미터를 갖는 것이 조금 특이하다. 또한 위의 예에서 Perl이 어떤 경우에 숫자를 문자열로 자동 변환하는지 주목하기 바란다.
또 한가지 짚고 넘어갈 것이 있다. 문자열 연결은 겹 따옴표 인용부호를 사용한 문자열들을 삽입하는 경우에 묵시적으로 적용된다. 만약 어떤 값들의 리스트를 출력하는 경우 굳이 문자열 연결 연산자를 사용하지 않더라도 해당 문자열이 연결되어 출력된다.  다음 세 가지 예는 모두 같은 출력을 갖는다.
print $a . ' is equal to ' . $b . "\n";            # 연결 연산자
print $a, ' is equal to ', $b, "\n";               # 리스트
print "$a is equal to $b\n";                      # 삽입 치환
어느 경우에 어떤 방법을 사용할 지는 전적으로 프로그래머에게 달렸다.
아마 처음 보았을 때 "x" 연산자의 필요성을 그리 크게 느끼지 못할 수도 있을 것이다.  그러나 때때로 다음과 같이 아주 유용하게 쓰일 때가 있다.
print "-" x $scrwid, "\n";
위의 경우 화면의 폭($scrwid) 만큼 가로줄을 긋게 된다.(별도의 for 루프가 필요없다.)


대입 연산자
입 연산자는 이미 앞의 예에서 많이 보았을 것이다. =은 수학에서의 '같음'을 나타내는 것이 아니라 오른쪽 값을 왼쪽에 대입한다는 것을 명심해 주기 바란다.(수학에서의 '같음'을 나타내는 같음 연산자는 ==이다.)
앞서의 연산자와 마찬가지로 대입 연산자 또한 2진 삽입 연산자로서 연산자 좌우에 피연산자를 갖는다. 연산자의 오른쪽에는 임의의 값이나 수식이 올 수 있지만, 왼쪽에는 반드시 lvalue(변수나 배열의 유효한 저장 위치)라고 하는 피연산자가 와야 한다. 가장 흔한 대입 연산자의 사용은 단순한 대입으로서, 연산자 우측의 결과값을 좌측의 변수에 넣는 것이다.
$a = $b;
$a = $b + 5;
$a = $a * 3;
마지막 줄에서 같은 변수가 두 번 참조된 것을 주목하기 바란다. 한 번은 연산을 위해, 그리고 한 번은 대입할 때 사용되었으며 이것은 잘못 사용된 것이 아니다. C언어에서와 마찬가지로 이러한 경우 축약된 형태의 표기가 가능하다. 만약 다음과 같이 할 경우,
lvalue operator= expression                        # $var += 1
이것은 다음과 같이 해석되어 실행된다.
lvalue = lvalue operator expression                # $var = $var + 1
따라서 위의 경우 다음과 같이
$a *= 3;
"$a에 3을 곱한다"로 되는 것이다. 마찬가지로 Perl에 있는 거의 대부분의 2원 연산자에는 같은 방식이 적용된다.(C언어에서조차 없는 경우도 있다.)
$line .= "\n";                 # $line 끝에 개행문자를 추가.
$fill x= 80;                            # 문자열 $fill을 자신의 80회 반복으로 만들기.
$val ||= "2";                         # $val의 값이 지정되지 않았다면 2로 초기화.
앞서 성적처리 예제 프로그램의 6번째 줄에서 두 개의 문자열 연결 연산자를 볼 수 있으며, 이 중 하나는 대입 연산자이다. 그리고 14번째 줄에서는 +=연산자를 볼 수 있다.
어떤 대입 연산자를 사용하든지, 대입 연산의 반환값은 대입한 후의 최종 값이 된다. (Pascal과 같은 언어에서는 대입 연산 문장은 반환값이 없다.) 따라서 앞서 다음과 같은 예에서
chop($number = <STDIN>)
chop 함수는 $number의 최종 값을 파라미터로 갖는다. 이러한 대입 연산은 앞으로 성적 처리 예제 프로그램 4번째 줄과 같은 while 루프에서 자주 보게 될 것이다.


자동 증가 / 자동 감소 연산자
'$var += 1'과 같은 문장을 더욱 간단하게 하기 위해 Perl은 C언어에서와 같이 변수 값을 증가하거나 감소하기 위해 자동 증가 및 자동 감소 연산자를 제공하고 있다. 이들 자동 증감 연산자는 변수의 앞 뒤 어느 쪽에도 적용될 수 있으며, 언제 변수의 값을 변화시키는가에 따라 다르게 사용된다.
예이름결과++$a, $a++자동 증가$a에 1을 더하기--$a, $a--자동 감소$a에서 1을 빼기(표 1-3) 1원 산술 연산자
자동 증감 연산자를 변수의 앞에 위치할 경우, 사전 증가(혹은 사전 감소) 변수라고 하며, 해당 변수 값이 참조되기 전에 미리 변수의 값을 증감한다. 변수의 뒤에 연산자가 위치할 경우 사후 증가(혹은 사후 감소) 변수라고 하며 변수의 값이 참조되고 난 다음에 변수의 값을 증감하게 된다. 다음 예를 보자.
$a = 5;                #$a에 5를 대입한다
$b = ++$a;        #$b는 $a를 증가한 다음 값을 대입하게 되므로 6이 된다
$c = $a--;                #$c는 6, 그리고 $a는 감소되어 5가 된다
앞서 성적 처리 예제 프로그램의 15번째 줄에서 성적 하나마다 $scores변수를 자동 증가하도록 하여 나중에 전체 평균을 구할 때 사용하도록 했었다. 이때는 사후 증가 연산자($scores++)를 사용하였으나, 이 경우 lvalue가 없는(즉 lvalue가 피연산자 자신인 경우) 경우이므로 사전 증가 연산자를 사용해도 같은 결과를 갖게 된다. 이 때 연산의 반환값은 사용되지 않고 그냥 버려진다.


논리 연산자
논리 연산자는 프로그램 내에서 중첩 조건문을 사용하지 않고 다양한 기준으로 결정을 내리는 경우에 사용하는 연산자이다. 논리 연산자를 소위 "단락 판별" 연산자라고도 하는데, 이는 연산자 왼쪽의 인수의 값을 판별하는 것으로도 연산의 결과를 낼 수 있는 경우 오른쪽 인수의 결과값 판별을 건너 뛰는 성질을 갖고 있기 때문이다.
Perl에는 실제로 두 세트의 논리 연산자가 있다. 하나는 C언어에서 빌려 온 것들이고, 다른 하나는 알아보기 편한 영어 단어로 된 것들이며, 이들 두 가지는 동일한 결과를 낳는다.
예이름결과$a && $bAnd$a가 거짓이면 $a, 그렇지 않으면 $b$a || $bOr$a가 참이면 $a, 그렇지 않으면 $b! $aNot$a가 참이 아니면 참$a and $bAnd$a가 거짓이면 $a, 그렇지 않으면 $b$a or $bOr$a가 참이면 $a, 그렇지 않으면 $bnot $aNot$a가 참이 아니면 참(표 1-4) 논리 연산자
이러한 논리 연산자의 "단락 판별" 성질을 이용하여, 조건 실행문을 만드는 데에 이들 논리 연산자가 종종 사용되곤 한다. 앞서 성적 처리 예제에서와 같이 grades라는 파일을 여는 경우를 살펴보자.
open(GRADES, "grades") or die "Can't open file grades: $!\n";
파일을 여는 데 성공하면 다음 줄을 실행한다. 만약 파일을 여는 데 실패하면 die문장 이하의 오류 메시지를 출력하고 프로그램 실행이 중단된다.
글자 뜻대로, 위의 문장은 "grade를 열거나 혹은 종료!"가 된다. 다른 자연어의 예를 제외하고라도, 이러한 단락 판별 연산자를 사용하면 프로그램의 흐름을 눈으로 알아보기 쉽게 해 준다. 중요한 처리는 화면의 왼쪽에 위치하고 두 번째 처리는 화면의 오른쪽에 위치하게끔 하는 것이다.(위에서 $!변수는 운영체제에서 표시하는 오류 메시지를 담고 있다. 2장 특수 변수 참조) 물론 이들 논리 연산자는 전통적인 조건문, 즉 if나 while에서도 사용될 수 있다.


비교 연산자
비교, 혹은 관계 연산자는 두 개의 스칼라 값(숫자나 문자열)의 상호 관계를 비교할 때 사용된다. 비교 연산자는 두 종류의 것이 있는데, 하나는 숫자를 비교하기 위한 것이고 다른 하나는 문자열을 비교하기 위한 것이다. 표 2-6은 $a와 $b가 각각 비교 연산자의 왼쪽, 오른쪽 피연산자라고 가정한 경우를 나타낸 것이다.
비교숫자문자열결과같다==eq$a가 $b와 같으면 참같지 않다!=ne$a가 $b와 같지 않으면 참작다<lt$a가 $b보다 작으면 참크다>gt$a가 $b보다 크면 참작거나 같다<=le$a가 $b보다 크지 않으면 참비교<=>cmp같으면 0, $a가 크면 1, $b가 크면 -1(표 2-5) 숫자, 문자열 비교 연산자
표 2-6의 마지막 연산자인 <=>와 cmp는 다른 연산자와 중복되지만, 때때로 sort  서브루틴과 같은 경우에 매우 유용하게 사용되기도 한다.(3장 참조).


파일 테스트 연산자
파일 테스트 연산자는 특정 파일에 대해 어떤 일을 하기 이전에 파일에 대한 다양한 정보를 알아낼 수 있도록 해 준다. 예를 들어 /etc/passwd라는 파일이 있는지 미리 알아본 후에 없으면 새로운 파일을 만드는 것이, 무턱대고 만들어서 기존에 갖고 있던 정보를 지우는 것보다 나을 것이다. 표 2-7에 이러한 파일 테스트 연산자의 예를 보였다.
예이름결과-e $a존재 여부$a 파일이 존재하면 참-r $a읽기 가능$a 파일이 읽기 가능하면 참-w $a쓰기 가능$a 파일이 쓰기 가능하면 참-d $a디렉토리$a가 디렉토리이면 참-f $a파일$a 파일이 일반 파일이면 참-T $a텍스트 파일$a 파일이 텍스트 파일이면 참(표 1-6) 파일 테스트 연산자
여기 몇가지 예제가 있다:
-e "/usr/bin/perl" or warn "Perl is improperly installed\n";
-f "/vmunix" and print "Congrats, we seem to be running BSD Unix\n";
여기서 "일반 파일"은 "텍스트 파일"과 다르다는 점에 주목하기 바란다. /vmunix와 같은 이진 파일은 일반 파일에 속하지만 텍스트 파일은 아니다. 텍스트 파일은 이진 파일의 상대적 개념이고, 일반 파일은 디렉토리나 장치 파일(device file)과 같은 것의 상대적 개념을 뜻한다.
이 외에도 상당히 많은 수의 파일 테스트 연산자가 있다. 대부분의 파일 테스트 연산자는 일원 불린(Boolean) 연산자이다. 즉, 하나의 피연산자를 취하며 피연산자는 파일이나 파일 핸들이 되고, 그 반환값으로 참 혹은 거짓을 갖는다. 파일 테스트 연산자 중 일부는 파일의 크기나 시간 등 좀 더 자세한 값을 반환하는 경우도 있다.



제어 구조
지금까지 성적 처리 프로그램을 제외한 모든 예제는 선형구조였다. 즉, 프로그램 내의 순서대로 각 명령어가 실행되는 구조였다. 또한 몇몇 예에서는 단락 판별 연산자를 이용하여 상황에 따라 하나의 명령어가 실행되든지 혹은 실행되지 않도록 하는 것도 보았다. 물론 이러한 선형적인 프로그램도 매우 유용하지만(실제로 많은 수의 CGI 프로그램이 이에 해당한다), 조건식이나 루프 등을 사용한다면 보다 훌륭한 프로그램을 만들 수 있다. 이러한 관점에서 Perl을 제어 언어라고도 할 수 있다.
프로그램 내에서 제어를 하려면 먼저 무엇인가를 판정해야 하고, 무엇인가를 판정하기에 앞서 무엇이 참이고 무엇이 거짓인지를 알아야 할 것이다.


참이란?
앞의 예에서 몇몇 연산이 참이나 거짓을 반환한다고 했었다. 더 자세히 들어가기 전에 참에 대해 알아보도록 하자. Perl은 다른 대부분의 컴퓨터 언어와는 조금 다르게 참을 다루지만, Perl로 프로그래밍을 하다 보면 그 의미를 파악할 수 있을 것이다.
Perl에서의 참은 항상 스칼라 구문 내에서 평가된다. 따라서 스칼라가 가질 수 있는 다음과 같은 값들에 대해 참과 거짓이 정의된다.
1. ""과 "0"을 제외한 모든 문자열은 참이다.
2. 0을 제외한 모든 숫자는 참이다.
3. 모든 레퍼런스는 참이다.
4. 그 밖에 정의되지 않은 모든 값은 거짓이다.
실제로 3번과 4번 항은 1, 2번에서 유추할 수 있다. 임의의 레퍼런스(3번째 법칙)는 무엇인가를 가리키고 있는 번지를 담고 있고, 0이 될 수 없으므로 참이다. 또한 정의되지 않은 값은 항상 0이거나 널(Null) 문자열이므로 1번에 의해 거짓이 된다.
또한 만약 모든 것이 문자열이라는 전제하에서 2번 항도 1번으로부터 이끌어 낼 수 있다. 참과 거짓을 판별할 때 숫자에서 문자열로의 강제 전환이 이루어진다면, 숫자 0은 문자열 "0"이 될 것이므로 거짓이 된다. 그 외의 모든 숫자는 문자열 "0"이 될 수 없으므로 참이 될 것이다.  다음 예로 앞서 설명한 참과 거짓의 경우를 자세히 살펴보자.
0                # 문자열 "0"이 될 것이므로, 거짓
1                # 문자열 "1"이 될 것이므로, 참
10 - 10        # 10-10 은 0, 즉 문자열 "0"이므로, 거짓
0.00                # 0이 되고, 문자열 "0"이므로, 거짓
"0"                # 문자열 "0"이므로, 거짓
""                # 널 문자열이므로, 거짓
"0.00"                # 널 문자열도 아니고 문자열 "0"도 아니므로, 참
"0.00" + 0        # + 연산자에 의해 강제로 숫자 0이 되므로, 거짓
\$a                # $a의 레퍼런스이므로, 참(비록 $a가 거짓이어도)
undef()        # 정의되지 않은 값을 반환하는 함수이므로, 거짓
if 와 unless
앞서 논리 연산자가 조건문을 만드는 경우를 살펴보았다. 조금 더 복잡한 형태의 논리 연산을 행하는 것이 바로 if이다. if는 주어진 조건을 판단하여 조건이 참일 경우 if를 따르는 블록을 실행하도록 한다.
블록은 하나 혹은 그 이상의 문장으로 이루어져 있으며 중괄호 {}로 묶여 있다. if문이 해당 블록을 실행하기 때문에 if를 사용할 때에는 반드시 중괄호를 사용해야만 한다. C언어에서는 실행해야 할 코드가 한 줄일 경우 중괄호를 생략할 수 있으나 Perl에서는 그럴 수 없다.
if ($debug_level > 0) {    # Something has gone wrong. Tell the user.
    print "Debug: Danger, Will Robinson, danger!\n";
    print "Debug: Answer was '54', expected '42'.\n";
}
때로는 주어진 조건을 만족하여 해당 블록을 실행하는 것으로 충분하지 않는 경우가 있다. 그리고 주어진 조건을 만족하지 않을 때 다른 블록을 실행하도록 할 필요도 있을 수 있다. 물론 if를 두 번 사용해서 이러한 문제를 해결할 수도 있겠지만, Perl에서는 이런 경우 좀 더 간결한 방식을 사용한다. if에서 한 블록 다음에 옵션으로 else라고 하는 두 번째 조건문을 위치하여 주어진 조건이 거짓일 때 바로 다음의 블록을 실행하게끔 한다.
또한, 두 개 이상의 가지수를 갖는 조건문을 사용해야 할 경우도 있다. 이 경우 각 조건식에 해당하는 elsif를 계속 사용하여 문제를 해결할 수 있다.
if ($city eq "New York") {
    print "New York is northeast of Washington, D.C.\n";
}
elsif ($city eq "Chicago") {
    print "Chicago is northwest of Washington, D.C.\n";
}
elsif ($city eq "Miami") {
    print "Miami is south of Washington, D.C.  And much warmer!\n";
}
else {
    print "I don't know where $city is, sorry.\n";
}
if와 elsif는 순서대로 어느 하나가 참이 될 때까지 판별되며, 아무것도 참이 되지 않으면 else이하의 블록이 실행된다. 만약 이들 조건 중 어느 하나가 참이 되면 해당 조건 바로 다음의 블록이 실행되며 나머지 모든 블록은 건너뛰게 된다. 만약 if문에 해당하는 조건이 참인 경우에는 아무것도 하지 않고 거짓일 경우에만 실행하도록 하기 위해서는 if-else문에서 빈 블록을 사용하는 방법, if 조건을 반대로 하는 방법("이것이 참이 아닐 경우에 무엇인가를 실행하라")등이 있을 수 있으나 이런 경우에는 다음과 같이 unless를 사용하면 된다.
unless ($destination eq $home) {
    print "I'm not going home.\n";
}


반복(루프) 구문
Perl은 네 가지 반복 구문을 제공한다: while, until, for, foreach. 이들 구문은 같은 코드에 대해 반복 실행하도록 해 준다.
while과 until 루프
while과 until 루프는 if와 unless의 관계와 비슷하다. 우선 해당 구문의 조건식을 판별한다. 주어진 조건이 만족되면(즉 while에서 참, until에서는 거짓) 해당 블록이 실행된다.
while ($tickets_sold < 10000) {
    $available = 10000 - $tickets_sold;
    print "$available tickets are available.  How many would you like: ";
    $purchase = <STDIN>;
    chomp($purchase);
    $tickets_sold += $purchase;
}
만약 처음부터 주어진 조건이 만족되지 않으면 루프는 한 번도 실행되지 않음을 주목하기 바란다. 예를 들어 이미 10,000개의 티켓을 팔았다면 while 루프 다음에 다음과 같은 줄을 넣어야 할 것이다.
print "This show is sold out, please come back later.\n";
앞서 성적 처리 예제의 4번째 줄은 다음과 같다.
while ($line = <GRADES>) {
괄호 안의 대입 연산자에 의해 GRADES 파일 핸들에 해당하는 파일의 다음 줄을 읽어서 $line변수에 대입한 후 $line의 값이 반환되므로, while 조건문에서는 $line의 값이 참인가 거짓인가에 따라 다음 블록의 실행여부를 결정짓게 된다. 여러분 중에는 파일의 빈 줄이 입력되면 while 조건문이 거짓으로 판별하게 되지 않겠느냐고 생각하는 사람도 있을 지 모른다. 그러나 정답은 "아니다". 앞서 말한 대로 한 줄씩 입력되는 경우 빈 줄은 "\n"에 해당하는 줄바꿈 글자를 포함하고 있기 때문이다. 물론 "\n"는 앞서 참과 거짓의 정의에 따르면 거짓이 아니라 참이다. 따라서 주어진 조건을 만족하여 빈 줄이 중간에 있을 지라도 루프는 계속 실행되게 된다.
한편, 파일의 마지막에 도달하면 줄 입력 연산자(<>)는 정의되지 않은 값을 반환하므로 조건식은 거짓이 되어 루프의 실행이 종료된다. 따라서 Perl에서는 특별히 eof 함수를 사용하여 테스트를 할 필요가 없다.
실제로 Perl의 조건문에서는 모든 것이 자연스럽게 동작하도록 디자인되어 있다. 예를 들어 스칼라를 포함하는 배열은 자신의 길이를 반환하도록 되어 있으므로
while (@ARGV) {
        process(shift @ARGV);
}
위와 같은 예에서 @ARGV의 내용이 모두 없어질 때까지 루프가 실행된다.
for 문
다른 형태의 반복문은 for 루프이다. for 루프는 while 루프처럼 동작하지만 몇 가지 점에서 조금 다르다.(C 프로그래머는 쉽게 이해할 수 있을 것이다.)
for ($sold = 0; $sold < 10000; $sold += $purchase) {
    $available = 10000 - $sold;
    print "$available tickets are available. How many would you like: ";
    $purchase = <STDIN>;
    chomp($purchase);
}
for 루프의 조건에는 최대 3개의 식을 적을 수 있다. 루프 변수의 초기 상태를 정하는 식, 루프 변수의 상태를 테스트하는 식, 그리고 루프 변수의 상태를 변화시키는 식이 바로 그것이다. 루프가 시작되면 초기 상태를 설정하고 조건식을 판별한다. 조건식의 값이 참이면 블록이 실행된다. 블록의 끝까지 실행되고 나면 조건식을 다시 판별하여 역시 참이면 블록을 다시 반복한다. 조건이 참인 한 블록의 실행과 변수 상태의 변화는 계속 이루어진다.
foreach 문
Perl의 반복문 중 마지막은 foreach 문이다. foreach 는 배열 등과 같은 스칼라 값의 모음에 같은 코드를 반복 실행하고자 할 때 사용한다.
foreach $user (@users) {
    if (-f "$home{$user}/.nexrc") {
        print "$user is cool... they use a perl-aware vi!\n";
    }
}
foreach문에서 괄호 안의 식은 리스트이다. 리스트의 각 요소가 하나씩 루프 변수의 값으로 대입되어 루프의 블록이 실행된다. 이 경우 루프 변수는 리스트 요소의 복사값이 아니라 리스트 값 바로 그 자체이므로, 루프 내에서 루프 변수의 값을 바꾸면 원래 배열의 값을 바꾸는 것이 된다.
아마 전형적인 Perl 프로그램에서는 for 루프보다 foreach 루프를 많이 보게 될 것이다. Perl에서는 foreach문에서 필요한 리스트를 만들어 내는 것이 무척 쉽기 때문이다. 해쉬의 키를 정렬하여 매 키 값마다 루프를 실행하는 다음과 같은 예제도 Perl에서 흔히 볼 수 있는 것 중 하나이다.
foreach $key (sort keys %hash) {
실제로 성적 처리 예제의 9번째 줄은 바로 위의 예제에 해당하는 것이다.
실행 중지: next와 last
next와 last 키워드는 루프 안에서의 흐름을 바꿀 수 있도록 해 준다. 이것은 특별한 경우가 아니다. 필요에 따라 루프의 실행을 건너 뛰어야 할 때도, 혹은 루프 전체를 빠져 나가야 할 때도 있을 수 있다. 예를 들어 UNIX 계정을 처리하는 경우, root나 lp같이 시스템이 사용하는 계정은 건너 뛰어야 할 때, next 키워드를 이용하여 현재 루프의 맨 마지막으로 옮겨 다음 번 루프를 실행하도록 할 수 있다. last 키워드는 전체 블록의 맨 마지막으로 건너 뛰어 마치 조건식이 거짓을 반환한 것처럼 루프를 빠져 나오게끔 한다. 예를 들어 아래 예와 같이 특별한 계정을 찾는 즉시 루프를 빠져 나오도록 하고 싶을 때에 이들 연산자를 사용하면 된다.
foreach $user (@users) {
    if ($user eq "root" or $user eq "lp") {
        next;
    }
    if ($user eq "special") {
        print "Found the special account.\n";
        # do some processing
        last;
    }
}
또한 루프에 레이블을 지정한 다음, 필요한 경우 여러 단계의 루프를 한꺼번에 빠져 나오도록 할 수도 있다. 구문 변환자(아직 설명하지 않았음)와 함께 사용하면 매우 효과적으로 루프를 빠져 나오도록 할 수 있다. 다음 예를 보자.
LINE: while ($line = <ARTICLE>) {
    last LINE if $line eq "\n";                 # 첫번째 빈 줄이 나오면 종료
    next LINE if $line =~ /^#/;                 # 주석을 건너뛰기
    # your ad here
}
여러분은 혹시 "잠깐, ^# 어쩌고 하는 부분이 무엇을 뜻하지요?" 하고 물을 지도 모른다. 이 부분은 정규 표현식(regular expression)을 포함한 패턴 일치 식으로서 다음 절에서 다룰 것이다. 무엇보다도 Perl은 텍스트 처리 언어로서, 정규 표현식은 Perl의 텍스트 처리의 핵심이다.





정규 표현식(Regular Expression)
정규 표현식은 grep, sed, awk등과 같은 많은 수의 UNIX 프로그램, vi, emacs와 같은 문서 편집기, 그리고 쉘 등과 같이 다양한 곳에서 사용되고 있다. 정규 표현식을 사용하면 복잡한 문자열을 간단한 방법으로 표현할 수 있다.
Perl에서는 정규 표현식을 여러 가지 경우에 사용한다. 가장 흔한 예는, 특정한 문자열이 주어진 패턴과 일치하는 지 판단하는 경우이다.예를 들어 /foo/ 와 같은 것은 패턴 일치 연산자로서, 주어진 문자열 내에 "foo"가 포함되어 있는 지를 판단하는 경우에 사용된다.
두 번째는, 문자열 내에서 특정 패턴을 찾은 후 원하는 다른 문자열로 바꿀 때이다. 프로그램 내에서 s/foo/bar와 같이 나타내면 "foo"라는 문자열을 찾고, "foo"대신 "bar"로 바꾸라는 뜻이다. 이것을 치환 연산자라고도 한다.
마지막으로, split 연산자를 사용하여 주어진 데이터를 원하는 단위로 쪼개는 데에도 정규 표현식을 사용한다. 이 때 데이터를 구분하는 단위를 구획 문자(delimiter) 라고 하며, 구획 문자를 정의하는데 정규 표현식을 사용한다. 앞서 성적 처리 예제의 5번째 줄과 12번째 줄에서 공백 문자를 구획 문자로 사용하여 각 줄에서 이름과 성적을 뽑아 내는 데 split 연산자를 사용했었다. 이와 같이 정규 표현식을 사용하여 임의의 구획 문자를 지정, 주어진 문자열을 쪼갤 수 있다.
(패턴 일치를 판단하는 경우 영문자의 대소문자를 구별하지 않는 등, 다양한 방법으로 패턴 일치를 할 수 있게끔 하는 여러 가지 변환자(modifier)가 있다. 나중에 2장에서 자세히 다룰 것이다.)
정규 표현식의 가장 간단한 사용 예는 주어진 글자가 일치하는 지의 여부를 판단하는 경우이다. 만약 문자열과 같이 여러 글자가 주어졌을 경우, 서브 문자열과 같이 해당 문자열이 포함되어 있는 지의 여부를 판별하게 된다. 예를 들어 주어진 HTML 파일에서 다른 HTML 파일로의 연결이 되어 있는 곳을 모두 찾아서 나타내고자 할 때, 이러한 연결은 http:라는 문자열이 항상 나타나므로 다음과 같이 찾을 수 있다.
while ($line = <FILE> ) {
        if ($line =~ /http:/) {
                print $line;
        }
}
여기서 =~는 패턴 일치 연산자로서 주어진 정규 표현식 http:이 $line과 일치하는 지 살펴 본다. 만약 $line에 "http:"와 일치하는 문자열이 있으면, if 판별식은 참을 반환하고 print명령에 해당하는 블록이 실행된다. 만약 =~ 연산자를 사용하지 않으면, Perl은 $line대신 기본 변수인 $_에서 정규 표현식을 판별한다. Perl에서는 대부분의 연산자가 기본적으로 $_를 사용하도록 되어 있으므로, 위의 예제는 다음과 같이 간략하게 만들 수 있다.
while (<FILE>) {
        print if /http:/;
}
위와 같이 간단한 경우 외에, HTTP연결 외의 다른 모든 연결을 찾아야 한다면 어떻게 해야 할까? 예를 들어 "http:", "ftp:", "mailto:"등을 모두 찾는 경우, 찾아야 할 연결이 하나 늘어날 때마다 비교해 볼 내용이 다음과 같이 늘어나야 할 것이다.
while (<FILE>) {
        print if /http:/;
        print if /ftp:/;
        print if /mailto:/;
}
정규 표현식을 사용하여 위의 경우를 다음과 같이 단순화할 수 있다. 즉 몇 개의 알파벳으로 이루어진 단어 뒤에 콜론(:)이 오는 문자열(http:, ftp:, mailto: 등)을 찾는 경우이므로 정규 표현식으로는 /[a-zA-Z]+:/와 같이 나타낼 수 있다. 여기서 대괄호([ ])는 문자 클래스(character class)를 의미한다. a-z와 A-Z는 모든 알파벳의 대, 소문자를 가리키는 것으로서, -기호는 양쪽 글자를 포함하여 그 사이에 있는 모든 글자를 나타낼 때 사용한다. 그리고 +는 특별한 글자로서, "+앞에 있는 글자가 하나 혹은 그 이상"을 나타낸다. 이렇게 특정한 무엇인가를 반복하도록 하는 것을 수량자(quantifier)라고 한다.( "/"는 정규 표현식의 일부가 아니라 패턴 일치 연산자의 일부로서, 정규 표현식을 포함하고 있다는 것을 알려 주는 역할을 한다.)
알파벳과 같이 자주 사용되는 클래스에 대해 Perl에서는 사용하기 편리하도록 미리 정의해 놓았는데 표 1-7이 그것이다.
이름정의코드공백[ \t\n\r\f]\s문자[a-zA-Z_0-9]\w숫자[0-9]\d(표 1-7) 정규 표현 문자 클래스
위 클래스는 "한 글자와의 일치 여부"를 판단하는 데 사용됨을 주의하기 바란다. 즉 \w는 한 단어와 일치하는 지의 여부를 판단하는 것이 아니라, 일반적인 단어를 구성하는 영문자 한 글자의 일치 여부를 판단하는 데 사용된다.(따라서 단어 일치를 판별하려면 앞서의 +수량자를 사용하여 \w+와 같이 나타내면 된다.) 또한 Perl에서는 이들 문자 클래스의 글자를 대문자로 하면 그 의미가 반대로 되는데, 예를 들어 숫자가 아닌 경우는 \D와 같이 나타내면 된다.
(\w가 [a-zA-Z_0-9]와 일치하지 않을 수도 있다는 점을 주의하기 바란다. 몇몇 로케일(locale)에서는 일반적인 ASCII외의 글자를 사용할 수도 있는데, 이 경우에도 \w는 단어 글자를 나타내는 데 사용된다.)
이 밖에 아주 특별한 문자 클래스로서 "."가 있다. "."는 임의의 한 글자와 일치함을 나타낸다. 예를 들어, /a./이라고 했을 경우 a를 포함한 문자열 중 a다음에 어느 한 글자가 따라 오는 것을 의미한다. 따라서 "at"나 "am", "a+"등과는 일치하지만, "a"는 a다음에 .에 해당하는 글자가 없기 때문에 일치하지 않는다. 이러한 패턴은 문자열 내에 임의의 위치에 존재할 수 있으므로, "oasis"나 "camel"과도 일치하나 "sheba"와는 일치하지 않는다. "caravan"의 경우 첫 번째 a와 두 번째 a 모두 일치하지만, 첫 번째 a에서 일치하는 것으로 패턴 일치를 마치게 된다.


수량자(Quantifier)
앞서 언급한 문자, 혹은 문자 클래스는 한 글자의 일치 여부를 판별하기 위한 것이다.  앞서 예에서 보았듯이, 여러 개의 단어 글자의 일치 여부를 알아 보기 위해서 \w+를 사용했었다. 여기서 +는 수량자의 일종으로서, 이 밖에도 여러 가지 수량자가 존재한다. (이들 수량자는 그 개수를 나타내기 위한 아이템 바로 뒤에 위치한다.)
가장 일반적인 수량자는 특정한 아이템이 일치하는 최소와 최대 횟수를 지정하는 것이다. 이 경우 {}안에 쉼표로 구분된 두 개의 숫자로 최소와 최대 횟수를 표시한다. 예를 들어 북미지역의 전화번호를 나타낼 때, /\d{7,11}/과 같이 하여 최소 숫자 7개, 최대 숫자 11개로 이루어진 전화번호를 표시할 수 있다. 만약 {}안에 숫자를 하나만 적으면 최소와 최대 횟수를 동일하게 하는 것으로, 즉 {}앞의 아이템이 정확하게 숫자 만큼 일치하는 것을 나타낸다.
만약 최소와 쉼표를 적고 최대를 적지 않는 경우는 최대 횟수가 무한대가 된다. 다시 말해서, 최소 숫자 이상 임의의 숫자 만큼 일치하는 것을 의미한다. 예를 들어 /\d{7}/ 이 국번을 포함한 전화번호 7자리를 의미하는 데 비해 /\d{7,}/은 7자리 이상의 모든 전화번호를 나타내는 것이다. 이와 반대로 최대 몇 번 같은 글자의 일치를 표현하는 방법은 없으므로, /.{0,5}/와 같이 임의의 글자가 최대 5번 나타나는 것으로 대신해야 한다.
이와 같은 최소․최대값에 대한 조합이 많기 때문에 Perl에서는 이들 중 몇 가지를 미리 정의해 놓았다. 앞서 본 +는 {1,} 즉 "바로 앞의 아이템이 최소 1번 이상"을 나타내는 것이다. 또한 *는 {0,} 즉 "바로 앞의 아이템이 0번, 혹은 그 이상"을 나타내는 데 사용된다. 그리고 ?는 {0,1}로서 "바로 앞의 아이템이 없거나, 혹은 1번 있음"을 표시하는 것이다.
이러한 수량자를 사용할 때 주의해야 할 점이 있다. 이들 수량자는 주어진 문자열에서 가능한 한 많은 수의 글자와 일치하려고 한다는 것이다. 예를 들어 /\d+/를 "1234567890"과 일치시킬 경우, /\d+/는 전체 문자열과 일치하는 결과를 가져 온다.  또한 "."를 사용하여 일치 여부를 판별할 때, 수량자의 사용이 예상치 못했던 결과를 가져 오기도 한다. 예를 들어,
spp:Fe+H20=FeO2;H:2112:100:Stephen P Potter:/home/spp:/bin/tcsh
와 같은 문자열이 주어지고 "spp"를 찾기 위해 /.+:/를 사용할 경우, +수량자는 앞서 말한 대로 가능한 한 많은 수의 글자와 일치하려고 하기 때문에 결과적으로 spp부터 /home/spp:까지의 긴 문자열 전체와 일치하는 결과를 가져 온다. 이런 결과를 피하기 위해서는 부정 문자 클래스, 즉 /[^:]+:/와 같이 나타내면 된다. 다시 말해 "하나 혹은 그 이상의 ":"이 아닌 글자와 일치한 다음, 마지막에 :과 일치"하는 문자열을 찾게 하는 것이다. 여기서 ^는 []로 둘러 싸인 문자 클래스 전체를 부정하는 역할을 한다. 정규 표현식의 사용에 있어서 또 다른 주의할 점은, 가능한 한 앞쪽에서 일치가 일어난다는 사실이다. 이것은 바로 위에서 표시했던 가능한 한 많은 수의 글자와 일치하는 것보다 우선 순위가 높게 동작한다. 문자열에서의 일치는 왼쪽에서 오른쪽으로 이루어지므로, 주어진 문자열의 오른쪽에 더 길게 일치할 수 있더라도 문자열의 왼쪽에 그 패턴이 존재하면 그 곳에서 일치가 이루어진다는 사실이다. 예를 들어 치환 명령(s///)을 사용하여 기본 변수 영역($_)에서 "x"로 이루어진 문자열을 없애고 싶을 경우,
$_ = "fred xxxxxxx barney";
s/x*//;
위와 같이 하면 결과적으로는 아무런 일도 일어나지 않는다. 왜냐하면, x*(0 혹은 그 이상의 "x")에 의해 문자열의 시작 부분에서 "f"가 나오기도 전에 무조건 일치하기 때문이다.
또 알아야 할 것이 있다. 수량자는 바로 앞의 한 글자에만 적용되기 때문에 /bam{2}/ 는 "bamm"과는 일치하나 "bambam"과는 일치하지 않는다. 만약 한 글자 이상과 일치하려면 괄호를 사용해서 /(bam){2}/과 같이 묶어 주어야 한다.


최소 일치
만약 구 버전의 Perl을 사용하면서 가능한 한 많은 글자 수와 일치하는 기능을 사용하고 싶지 않다면 부정 문자 클래스를 사용하여야 한다. 최신 버전의 Perl에서는 임의의 수량자 뒤에 물음표(?)를 추가하여, 가능한 많은 글자수와 일치하지 않도록(최소한의 글자수와 일치하도록) 지정할 수 있다. 앞서의 spp라는 사용자 문자열 일치의 경우, /.*?:/ 와 같이 할 수 있다. 즉 .*?은 .*와 달리 가능한 한 적은 숫자의 글자와 일치하기 때문에 첫 번째 콜론까지(spp:)만 일치하게 된다. 일치 경계 제한특정 패턴의 일치 여부를 판별할 경우, 주어진 문자열에서 패턴이 일치하는 모든 부분에 대해 패턴의 일치 여부를 찾게 된다. 이 경우 앵커(anchor)를 사용해서 패턴이 문자열에서 일치하는 부분을 제한할 수 있다. 앵커 자체는 무엇과도 일치하지는 않지만, 앵커가 둘러싸고 있는 패턴의 일치를 구체적으로 제한한다는 것을 주목하기 바란다.
특수 문자열 \b는 단어의 경계를 나타낸다. 예를 들어
/\bFred\b/
는 "The Great Fred"나 "Fred the Great"와는 일치하지만 "Frederick the Great"와는 일치하지 않는다. 왜나하면, "Frederick"에서의 "de"가 단어 경계를 포함하고 있지 않기 때문이다.
문자열의 시작과 끝을 나타내기 위한 앵커도 있다. 캐럿(^)은 문자열의 시작을 의미한다. 예를 들어 /^Fred/는 "Frederick the Great"와는 일치하지만 "The Great Fred"와는 일치하지 않는다. 달러 표시($)는 문자열의 끝을 나타낸다.
따라서 다음과 같이 했을 경우,
next LINE if $line =~ /^#/;
윗 줄은 '만약 이 줄이 #으로 시작하면 LINE 루프의 다음으로 가라‘라는 것을 의미한다.(역자주: #으로 시작하는 주석문을 처리할 때 사용된다)

백 레퍼런스
앞서 언급했듯이 수량자를 사용할 경우 한 글자 이상에 대해 적용할 때는 괄호를 사용해야 했다.  정규 표현식 내의 괄호는 이 밖에도 일치된 패턴을 기억했다가 나중에 재참조할 경우에도 사용된다. 이 경우 괄호를 사용했을 때와 사용하지 않았을 때 패턴의 일치에는 전혀 차이가 없다. 예를 들어 /\d+/와 /(\d+)/는 가능한 한 많은 하나 이상의 숫자와 일치한다는 점에서는 차이가 없다. 그러나 두 번째만이 프로그램 내에서 일치된 패턴을 나중에 다시 참조하고 싶을 경우 사용할 수 있다.
괄호를 사용해 기억된 패턴을 나중에 어떻게 다시 참조하는가는 재참조하는 위치에 따라 달라진다. 같은 정규 표현식 내에서는 역슬래쉬(\) 다음에 숫자를 적어 주어진 정규 표현식의 처음부터 괄호의 순서대로 재참조할 수 있다. 예를 들어 HTML태그와 같은 문자열을 찾을 경우, 주어진 문자열이 "<B>Bold</B>"라면 정규 표현식으로는 /<(.*?)>.*?<\/\1>/과 같이 나타낼 수 있다. 따라서 \1로 나타낸 부분은 앞서의 (.*?)에서 나타낸 부분과 같은 "B"를 찾게 된다.
정규 표현식 밖에서는 $뒤에 숫자를 적어 표시한 스칼라 변수로 재참조를 지정한다.  예를 들어 문자열에서 처음 두 단어의 위치를 바꾸고 싶을 경우 간단하게
s/(\S+)\s+(\S+)/$2 $1/
와 같이 하면 된다.
위의 예에서 보이듯이 변수 치환과 정규 표현식을 이용한 패턴 일치로 인해 Perl이 텍스트 처리에 뛰어나다는 점을 알 수 있다.



리스트 처리
이 장의 앞 부분에서 Perl에는 스칼라(단수를 표시하는 데 사용)와 리스트(복수를 표시하는데 사용)가 있다고 언급했었다. 대부분의 전통적인 연산자들은 스칼라를 처리하는데 사용된다. 이들은 한 개의 인수(이진 연산자의 경우 두 개의 인수)를 취하며, 심지어 리스트 연산의 경우에도 단수의 결과값을 갖는다.
  예를 들어,
@array = (1 + 2, 3 - 4, 5 * 6, 7 / 8);
과 같은 경우, 우변에는 정확하게 4개의 값을 가짐을 알 수 있다. +, -와 같은 일반적인 수학 연산자는 결과값으로 항상 스칼라를 내놓기 때문이다. 따라서 배열에 값을 대입하는 리스트 연산에서도 이러한 단수 결과값이 적용된다.
그러나 몇몇 Perl연산자의 경우 사용되는 구문에 따라 스칼라 값을 만들거나 리스트 값을 만들기도 한다. 이 경우 스칼라 또는 리스트 값 중 어느 결과가 필요한 지는 자동으로 결정된다. 다음과 같은 몇 가지 개념을 이해하면 어떤 경우에 스칼라, 혹은 리스트 값이 생성되는지 알 수 있을 것이다.
첫째로, 리스트는 무엇인가에 "둘러 싸여" 만들어 진다. 위의 예의 경우, 리스트 대입 연산이 그것이다. 다음 2장과 3장의 많은 예에서 LIST를 인수로 갖는 다양한 연산자를 볼 수 있을 것이다. 이러한 연산자는 리스트 구문을 만들어 내는 연산자이다. 이 책에서는 LIST를 "리스트 구문을 만드는 문법적 구조체"라는 기술적 용어로 정의하도록 하겠다. 예를 들어 sort의 경우 다음과 같은 문법 요약을 찾을 수 있을 것이다.
sort LIST
이 경우 sort는 리스트를 인수로 전해 준다.
둘째로, 컴파일시에, LIST를 갖는 임의의 연산자는 LIST의 각 요소에게 리스트 구문을 제공한다. 따라서 LIST내의 최상위 연산자나 요소는 리스트를 만들어 내야 한다는 것을 알고 있다. 예를 들어,
sort @guys, @gals, other();
라고 했을 경우, @guys, @gals, other()는 각각 리스트 값을 만들어 내야 한다는 것을 알고 있다는 뜻이다.
마지막으로, 실행시에, 각 LIST요소는 순서대로 리스트를 생성해 내며, 그리고 나서 (여기서부터가 중요함) 각각 구분된 리스트가 하나로 합해진 다음 하나의 큰 리스트로 만들어 진다. 그 결과 최종적으로 하나의 일차원 리스트가 LIST를 인수로 했던 함수에 전달된다.  
앞의 예에서 만약 @guys가 (Fred,Barney)이었고, @gals가 (Wilma,Betty)였으며, others()함수가 하나의 요소를 갖는 리스트 (Dino)를 반환했다면 최종적으로 sort가 취하게 되는 LIST는 (Fred,Barney,Wilma,Betty,Dino)가 되며, sort가 반환하는 값은(Barney,Betty,Dino,Fred,Wilma)가 된다. 몇몇 연산자는 리스트를 만들어 내기도 하고(예: keys), 또 일부는 리스트를 받아들이기만 하며(예: print), 또 일부는 다른 형태의 리스트로 변환하기도 한다.(예: sort). 다른 형태의 리스트로 변환하는 연산자는 필터의 한 형태로 볼 수 있으며, 쉘에서와는 달리 데이터의 흐름은 오른쪽에서 왼쪽으로 진행한다. 이들 연산자는 인수를 오른쪽에서부터 취하기 때문이다. 다음과 같이 몇몇 리스트 연산자를 한 줄에 동시에 표기할 경우,
print reverse sort map {lc} keys %hash;
우선 %hash의 키 값 리스트를 얻은 후 map함수에 전달하고, map함수는 모든 키 값을 lc 연산자에 의해 모두 소문자로 변환한다. 그 다음 sort함수에 의해 순서대로 나열된 후, reverse함수에 의해 리스트 요소의 순서를 반대로 만들고 그 결과를 출력하게 되는 것이다.



여러분이 모르는 것
다치게 하고 싶지 않아요.(진심!)
휴... 다시 자연어로서 Perl에 대해서 생각할 시간이다. 자연어를 사용하는 사람들은 다른 숙련도를 가지고 있고, 그 언어를 말하고, 말하는 만큼 배우고, 그리고 일반적으로 언어를 잘 사용하게 된다는 것을 인정한다. 여러분이 영어의 모든 것을 알지 못하는 것처럼 Perl의 모든 것에 대해서 아직 알지 못한다. 그러나 Perl에서는 그것이면 족하다. 심지어 여러분에게 자기자신의 함수를 작성하는 것에 대해서 설명하지 않아도 Perl을 가지고 유용하게 프로그램을 만들 수 있다. 시스템 관리 언어나 네트웍 언어 또는 객체 지향 언어로서의 Perl에 대해서 설명조차 거의 하지 않았지만 말이다. 앞으로 이러한 것들에 대해서 쓸 것이다.(생각해 보니, 이미 쓴 것 같다)
그러나 마지막으로, 여러분은 Perl에 관한 여러분 자신의 관점을 만들기 바란다. 그것은 창조의 고통을 받는 아티스트로서의 여러분의 특권이다. 여러분에게 우리가 페인트 하는 방법을 설명하지 여러분이 페인트 하는 방법을 설명하지는 않는다. 왜냐하면 한가지 일을 하는데에는 많은 방법이 있기 때문이다.

  Hit : 10137     Date : 2008/12/18 05:04



    
똥마루 아직 읽어보진 않았는데 이 글이 두려운 이유는 뭘까? 2009/01/10  
1500   컴구조 파악하기 위한 강좌     asd2862
11/19 8263
1499   해커가 되기위해 알아야할 30가지 출처 :해커대학[5]     asdzxc301
12/12 12232
1498   윈도우 도스 명령어(?)[1]     asdzxc301
12/13 8912
1497   빌게이츠에 대해서[2]     asdzxc301
12/13 8769
1496   어셈블리어 총정리 강좌     asdzxc301
12/13 18970
1495   어셈블리어 강좌 1편[1]     asdzxc301
12/13 12680
1494   어셈블리어 강좌 2편     asdzxc301
12/13 7967
1493   어셈블리어 강좌 3편     asdzxc301
12/13 8910
1492   어셈블리어 강좌 4편     asdzxc301
12/13 10584
1491   어셈블리어 강좌 5편     asdzxc301
12/13 20075
1490   어셈블리어 강좌 6편     asdzxc301
12/13 7973
1489   어셈블리어 강좌 7편 마지막요 ㅎㅎ[2]     asdzxc301
12/13 9986
1488   초짜를 위한 파이썬[2]     asdzxc301
12/18 15685
1487   펄과 파이썬 프로그래밍 서적     asdzxc301
12/18 8562
  펄1[1]     asdzxc301
12/18 10136
1485   포맷 스트링 버그 분석     asdzxc301
12/24 10407
1484   [1장]바이러스의 정의 & 위험성[5]     작은해커
12/02 6628
1483   FTP 설정 오류를 이용한 버그 공격(먹히는 곳도 있을 것이고...아닐수도..)ㅋ[4]     작은해커
11/30 6967
1482   [2장]바이러스의 종류와 특징[5]     작은해커
12/10 7783
1481   bof & fsb 에 유용한 펄 스크립트[5]     awsedr45
03/11 11090
[1][2][3][4] 5 [6][7][8][9][10]..[79]

Copyright 1999-2023 Zeroboard / skin by Hackerschool.org / Secure Patch by Hackerschool.org & Wowhacker.com