펄 언어 구조

**[[펄]] 프로그래밍 언어의 구조**는 언어의 문법 규칙과 프로그램이 구성되는 일반적인 방식을 모두 포함한다. 펄의 설계 철학은 일반적으로 인용되는 "어떤 일을 하는 데에는 하나 이상의 길이 있다"라는 표어에 표현되어 있다. 다중 패러다임, 동적 형식 언어로서 펄은 프로그램 설계에 상당한 유연성을 허용한다. 펄은 또한 모듈화를 장려한다. 이는 유닉스 기반의 구성 요소 기반 설계 구조에 기인하며, 100,000개 이상의 모듈로 구성된 커뮤니티 유지 관리 저장소인 CPAN 아카이브의 규모에 책임이 있다.

## 기본 문법
펄에서 최소한의 ""Hello, World!" 프로그램"은 다음과 같이 작성할 수 있다.

```perl
print "Hello, World!\n"
```

이것은 출력한다 문자열 Hello, World! 와 새 줄, 기호적으로 `n` 문자로 표현되며, 이 문자의 해석은 선행하는 이스케이프 문자(역슬래시)에 의해 변경된다. 버전 5.10부터 새로운 'say' 내장 함수는 훨씬 더 간단하게 동일한 효과를 낸다.

```perl
say "Hello, World!"
```


전체 펄 프로그램은 펄에 대한 명령줄 매개변수로도 지정될 수 있으므로, 동일한 프로그램은 명령줄에서도 실행될 수 있다 (유닉스의 예시):

```perl
$ perl -e 'print "Hello, World!\n"'
```


이 프로그램의 정식 형태는 약간 더 길다:


```perl
#!/usr/bin/env perl
print "Hello, World!\n";
```


해시 마크 문자는 펄에서 주석을 나타내며, 코드 줄의 끝까지 이어지고 컴파일러에 의해 무시된다 (Windows 제외). 여기에 사용된 주석은 특별한 종류이다: 이것은 셔뱅 줄이라고 불린다. 이는 유닉스 계열 운영 체제에 펄 인터프리터를 찾도록 지시하여, `perl`을 명시적으로 언급하지 않고도 프로그램을 호출할 수 있게 한다. (마이크로소프트 윈도우 시스템에서 펄 프로그램은 일반적으로 `.pl` 확장자를 펄 인터프리터와 연결하여 호출된다는 점에 유의하라. 이러한 상황을 처리하기 위해 `perl`은 셔뱅 줄을 감지하고 스위치를 위해 파싱한다.)

정식 형태의 두 번째 줄에는 펄에서 문장을 구분하는 데 사용되는 세미콜론이 포함되어 있다. 블록이나 파일에 단일 문장만 있는 경우 구분 기호는 불필요하므로 프로그램의 최소 형태에서 또는 일반적으로 블록이나 파일의 마지막 문장에서 생략할 수 있다. 정식 형태에는 포함되어 있는데, 이는 편집을 더 쉽게 만들기 위해 불필요할 때도 모든 문장을 종료하는 것이 일반적이기 때문이다: 세미콜론을 조정할 필요 없이 블록이나 파일의 끝에 코드를 추가하거나 이동할 수 있다.

펄 버전 5.10은 출력에 새 줄 문자를 암묵적으로 추가하는 `say` 함수를 도입하여, 최소한의 "Hello World" 프로그램을 더욱 짧게 만든다.


```perl
use 5.010; # 새로운 5.10 함수를 가져오려면 반드시 있어야 하며, 5.10이 아닌 5.010에 유의
say 'Hello, World!'
```


## 자료형

펄에는 여러 가지 기본적인 자료형이 있다. 가장 일반적으로 사용되고 논의되는 것은 스칼라, 배열, 해시, 파일 핸들, 그리고 서브루틴이다.

### 스칼라 값

문자열 값(리터럴)은 따옴표로 묶어야 한다. 문자열을 이중 따옴표로 묶으면 문자열에 나타나는 변수 이름의 값이 문자열에서 변수 이름을 자동으로 대체(또는 **[[변수 삽입|삽입]]**됨)할 수 있다. 문자열을 작은 따옴표로 묶으면 변수 삽입이 방지된다.

예를 들어, `$name`이 `"Jim"`인 경우:

* 그러면 `print("My name is $name")`은 `"My name is Jim"`을 출력한다 (이중 따옴표 내 삽입).
* 하지만 `print('My name is $name')`은 `"My name is $name"`을 출력한다 (작은 따옴표 내 삽입 없음).

문자열에 큰따옴표를 포함시키려면 앞에 백슬래시를 붙이거나 문자열을 작은따옴표로 묶어야 한다. 작은따옴표를 포함시키려면 앞에 백슬래시를 붙이거나 문자열을 큰따옴표로 묶어야 한다.

문자열은 `q` 및 `qq` 따옴표와 유사한 연산자를 사용하여 따옴표로 묶을 수도 있다.
* `'this'`와 `q(this)`는 동일하다.
* `"$this"`와 `qq($this)`는 동일하다.

마지막으로, 여러 줄 문자열은 히어 도큐먼트를 사용하여 정의할 수 있다.


```perl
$multilined_string = <<EOF;
This is my multilined string
note that I am terminating it with the word "EOF".
EOF
```


숫자(숫자 상수)는 따옴표가 필요하지 않다. 펄은 숫자를 문자열로, 문자열을 숫자로 변환하며 이는 사용되는 컨텍스트에 따라 달라진다. 문자열이 숫자로 변환될 때, 문자열의 뒤따르는 비숫자 부분은 버려진다. 문자열의 선행 부분이 숫자가 아닌 경우, 문자열은 숫자 0으로 변환된다. 다음 예시에서 문자열 `$n`과 `$m`은 숫자로 취급된다. 이 코드는 숫자 '5'를 출력한다. 변수의 값은 동일하게 유지된다. 펄에서 `+`는 항상 숫자 덧셈 연산자이다. 문자열 연결 연산자는 마침표이다.


```perl
$n = '3 apples';
$m = '2 oranges';
print $n + $m;
```

분수 값을 정수 값으로 반올림하는 함수가 제공된다. `int`는 소수 부분을 잘라내어 0으로 반올림하고, `POSIX::ceil`과 `POSIX::floor`는 각각 항상 올림과 항상 내림을 수행한다. `printf "%f"` 또는 `sprintf "%f"`의 숫자-문자열 변환은 짝수로 반올림하며, 은행원 반올림을 사용한다.

펄에는 조건문을 평가하는 데 사용하는 불리언 컨텍스트도 있다. 다음 값들은 모두 펄에서 거짓으로 평가된다.


```perl
$false = 0; # 숫자 0
$false = 0.0; # 실수 0
$false = 0b0; # 이진수 0
$false = 0x0; # 십육진수 0
$false = '0'; # 문자열 "0"
$false = ""; # 빈 문자열
$false = (); # 빈 리스트
$false = undef; # undef의 반환 값
$false = 2-3+1 # 0으로 계산되어 "0"으로 변환되므로 거짓이다
```


다른 모든 (0이 아닌) 값은 참으로 평가된다. 여기에는 이상한 자기 설명 리터럴 문자열 "0 but true"도 포함되는데, 이는 사실 숫자로는 0이지만, 불리언으로 사용될 때는 참이다. 모든 비숫자 문자열도 이 속성을 가지지만, 이 특정 문자열은 숫자 경고 없이 펄에 의해 잘린다. 이 문자열의 덜 명시적이지만 개념적으로 더 이식성이 높은 버전은 * 또는 *인데, 이는 문자가 0으로 평가되는 것에 의존하지 않는다. 왜냐하면 '0E0'은 문자 그대로 0 곱하기 10의 0제곱이기 때문이다. 빈 해시 `{}`도 참이다. 이 컨텍스트에서 `{}`는 빈 블록이 아니다. 왜냐하면 `perl -e 'print ref {}'`는 `HASH`를 반환하기 때문이다.

평가된 불리언 표현식도 스칼라 값이다. 문서는 참 또는 거짓의 특정 값이 반환된다고 약속하지 않는다. 많은 불리언 연산자는 참에 대해 1을 반환하고 거짓에 대해 빈 문자열을 반환한다.  함수는 변수에 어떤 값이 설정되었는지 여부를 결정한다. 위의 예에서 는 를 제외한 모든 값에 대해 참이다.

1 또는 0이 특별히 필요한 경우, 조건부 연산자를 사용하여 명시적인 변환을 수행할 수 있다.


```perl
my $real_result = $boolean_result ? 1 : 0;
```


### 배열 값

배열 값(또는 리스트)은 요소들을 나열하고 쉼표로 구분하며 괄호로 묶어(최소한 연산자 우선순위에 따라 필요한 경우) 지정한다.


```perl
@scores = (32, 45, 16, 5);
```


qw() 따옴표와 유사한 연산자는 따옴표와 쉼표를 입력하지 않고도 문자열 목록을 정의할 수 있게 한다. 괄호 대신 거의 모든 구분 기호를 사용할 수 있다. 다음 줄은 동일하다.


```perl
@names = ('Billy', 'Joe', 'Jim-Bob');
@names = qw(Billy Joe Jim-Bob);
```


`split` 함수는 구분 문자열이나 정규 표현식을 사용하여 문자열 표현식에서 분리된 문자열 목록을 반환한다.


```perl
@scores = split(',', '32,45,16,5');
```


목록의 개별 요소는 대괄호 안에 숫자 인덱스를 제공하여 접근한다. 스칼라 시길을 사용해야 한다. 범위 또는 숫자 인덱스 목록을 대괄호 안에 사용하여 하위 목록(배열 슬라이스)도 지정할 수 있다. 이 경우 배열 시길이 사용된다. 예를 들어, `$month[3]`은 `"April"`이고(배열의 첫 번째 요소는 인덱스 값 0을 가진다), `@month[4..6]`은 `("May", "June", "July")`이다.

### 해시 값

펄 프로그래머는 키/값 쌍 목록에서 해시(또는 연관 배열)를 초기화할 수 있다. 키와 값이 쉼표 대신 `=>` 연산자(때로는 fat comma라고 불림)로 구분되면 따옴표 없이(barewords) 사용할 수 있다. 다음 줄은 동일하다.


```perl
%favorite = ('joe', "red", 'sam', "blue");
%favorite = (joe => 'red', sam => 'blue');
```


해시의 개별 값은 해당 키를 중괄호 안에 제공하여 접근한다. `$` 시길은 접근된 요소를 스칼라로 식별한다. 예를 들어, 는 와 같다. 해시는 개별적으로 값을 설정하여 초기화할 수도 있다.


```perl
$favorite{joe}   = 'red';
$favorite{sam}   = 'blue';
$favorite{oscar} = 'green';
```


대신 `@` 시길을 사용하여 여러 요소에 접근할 수도 있다(결과를 목록으로 식별). 예를 들어,
은 와 같다.

### 파일 핸들

파일 핸들은 리소스에 대한 읽기 및 쓰기 접근을 제공한다. 이것들은 대부분 디스크의 파일이지만, 장치, 파이프, 또는 심지어 스칼라 값일 수도 있다.

원래 파일 핸들은 패키지 변수로만 생성할 수 있었고, 다른 변수들과 구별하기 위해 ALL_CAPS 규칙을 사용했다. Perl 5.6 이상은 명명된 파일 핸들 대신 스칼라 변수도 허용하며, 이 변수는 익명 파일 핸들에 대한 참조로 설정된다(자동 생성).

### 타입글로브 값

타입글로브 값은 심볼 테이블 항목이다. 타입글로브의 주요 용도는 심볼 테이블 별칭을 만드는 것이다. 예를 들어:


```perl
*PI = \3.141592653; # 상수 스칼라 $PI 생성
*this = *that; # 모든 데이터 타입 'this'를 모든 데이터 타입 'that'의 별칭으로 생성
```


### 배열 함수

배열의 요소 수는 스칼라 컨텍스트에서 배열을 평가하거나 `$#` 시길을 사용하여 결정할 수 있다. 후자는 배열의 마지막 요소 인덱스를 제공하며, 요소의 수가 아니다. scalar()와 (`$#array&nbsp;+&nbsp;1`) 표현식은 동일하다.

### 해시 함수

전체 해시에서 작동하는 몇 가지 함수가 있다. keys 함수는 해시를 받아 키 목록을 반환한다. 마찬가지로 values 함수는 해시의 값을 반환한다. 키와 값은 일관되지만 임의의 순서로 반환된다는 점에 유의한다.


```perl
# each을 호출할 때마다 다음 키/값 쌍이 반환된다.
# 모든 값이 결국 반환되지만 그 순서는
# 예측할 수 없다.
while (($name, $address) = each %addressbook) {
    print "$name lives at $address\n";
}

# 위와 유사하지만 알파벳순으로 정렬됨
foreach my $next_name (sort keys %addressbook) {
    print "$next_name lives at $addressbook{$next_name}\n";
}
```


## 제어 구조

펄에는 여러 종류의 제어 구조가 있다.

C, 자바스크립트, 자바 프로그래밍 언어와 유사한 블록 지향 제어 구조를 가지고 있다. 조건은 괄호로 둘러싸고, 제어되는 블록은 중괄호로 둘러싼다.

 label while ( cond ) { … }
 label while ( cond ) { … } continue { … }
 label for ( init-expr ; cond-expr ; incr-expr ) { … }
 label foreach var ( list ) { … }
 label foreach var ( list ) { … } continue { … }
 if ( cond ) { … }
 if ( cond ) { … } else { … }
 if ( cond ) { … } elsif ( cond ) { … } else { … }

단일 문장만 제어될 때는 문장 수정자가 더 간결한 문법을 제공한다.

 statement if cond ;
 statement unless cond ;
 statement while cond ;
 statement until cond ;
 statement foreach list ;

단락 논리 연산자는 표현식 수준에서 제어 흐름에 영향을 미치는 데 일반적으로 사용된다.

 expr and expr
 expr && expr
 expr or expr
 expr  expr

("and" 및 "or" 연산자는 && 및 와 유사하지만 우선순위가 낮아 전체 문장을 제어하는 데 더 쉽게 사용할 수 있다.)

흐름 제어 키워드 `next`(C의 `continue`에 해당), `last`(C의 `break`에 해당), `return`, `redo`는 표현식이므로 단락 연산자와 함께 사용할 수 있다.

펄에는 각각 두 가지 형태를 가진 두 가지 암시적 반복 구조도 있다.

 results = grep { … } list
 results = grep expr, list
 results = map { … } list
 results = map expr, list

`grep`은 제어되는 블록이나 표현식이 참으로 평가되는 리스트의 모든 요소를 반환한다. `map`은 리스트의 각 요소에 대해 제어되는 블록이나 표현식을 평가하고 결과 값의 리스트를 반환한다. 이러한 구조는 간단한 함수형 프로그래밍 스타일을 가능하게 한다.

5.10.0 릴리스 이전에는 펄 5에 Switch 문이 없었다. 5.10.0부터 `given`/`when`이라는 다중 분기 문이 다음 형식으로 제공된다.

 use v5.10; # 새로운 5.10 함수를 가져오려면 반드시 있어야 함
 given ( expr ) { when ( cond ) { … } default { … } }

문법적으로 이 구조는 다른 언어에서 발견되는 Switch 문과 유사하게 작동하지만 몇 가지 중요한 차이점이 있다. 가장 큰 차이점은 switch/case 구조와 달리 given/when 문은 명시적으로 정의된 break 명령을 기다리지 않고 첫 번째 성공적인 분기 후에 실행을 중단한다는 것이다. 반대로 switch 동작을 에뮬레이션하려면 명시적인 `continue`가 필요하다.

Perl 5.10을 사용하지 않는 사람들을 위해 Perl 문서는 다른 제어 구조를 사용하여 동일한 효과를 얻을 수 있는 6가지 방법을 설명한다. 또한 라쿠 언어의 기능을 모델로 한 Switch 모듈도 있다. 이는 소스 필터를 사용하여 구현되므로 비공식적으로 사용이 권장되지 않는다.

펄에는 `goto label` 문이 포함되어 있지만 거의 사용되지 않는다. 다른 언어에서 `goto`가 필요한 상황은 펄의 다양한 흐름 제어 옵션 때문에 자주 발생하지 않는다.

또한 꼬리 재귀를 수행하는 `goto &amp;sub` 문도 있다. 이것은 현재 서브루틴을 종료하고 지정된 `sub`를 즉시 호출한다. 이는 호출자가 Perl 자체보다 더 효율적인 스택 관리를 수행할 수 있는 상황(일반적으로 현재 스택에 변경이 필요 없는 경우)과 깊은 재귀에서 사용되며, 꼬리 호출은 반환 시 스코프/스택 관리 오버헤드를 피하므로 성능에 상당한 긍정적인 영향을 미칠 수 있다.

## 서브루틴
서브루틴은 `sub` 키워드로 정의되며 단순히 이름을 지정하여 호출한다. 해당 서브루틴이 아직 선언되지 않은 경우, 호출하려면 함수 이름 뒤에 괄호를 붙이거나 함수 이름 앞에 앰퍼샌드(**&**)를 붙여야 한다. 그러나 괄호 없이 **&**를 사용하면 현재 서브루틴의 인수가 호출되는 서브루틴으로 암시적으로 전달되며, 괄호와 함께 **&**를 사용하면 프로토타입이 무시된다.


```perl
# 서브루틴 호출

# 서브루틴이 코드의 나중에 정의되는 경우 여기서는 괄호가 필요하다.
foo();
&foo; # (이것도 작동하지만, 서브루틴에 전달되는 인수에 관한 다른 결과가 있다.)

# 서브루틴 정의
sub foo { … }

foo; # 여기서는 괄호가 필요하지 않다.
```


서브루틴 이름 뒤에 인수 목록을 제공할 수 있다. 인수는 스칼라, 목록 또는 해시가 될 수 있다.


```perl
foo $x, @y, %z;
```

서브루틴의 매개변수는 개수나 유형을 선언할 필요가 없으며, 실제로 호출마다 달라질 수 있다. 매개변수 유효성 검사는 서브루틴 내부에서 명시적으로 수행해야 한다.

배열은 요소로 확장되고, 해시는 키/값 쌍 목록으로 확장되며, 이 모든 것은 스칼라의 단일 평면 목록으로 서브루틴에 전달된다.

전달된 인수는 모두 특수 배열 `@_`에서 서브루틴에서 사용할 수 있다. `@_`의 요소는 실제 인수에 대한 참조이다. `@_`의 요소를 변경하면 해당 인수가 변경된다.

`@_`의 요소는 일반적인 방식으로 첨자를 사용하여 접근할 수 있다.


```perl
$_[0], $_[1]
```


그러나 결과 코드는 읽기 어려울 수 있으며, 매개변수는 참조에 의한 호출 의미론을 가지므로 바람직하지 않을 수 있다.

일반적인 관용구 중 하나는 `@_`를 명명된 변수 목록에 할당하는 것이다.


```perl
my ($x, $y, $z) = @_;
```


이것은 니모닉 매개변수 이름을 제공하고 값에 의한 호출 의미론을 구현한다. `my` 키워드는 다음 변수들이 포함하는 블록에 어휘적으로 스코프된다는 것을 나타낸다.

다른 관용구는 `@_`에서 매개변수를 shift하는 것이다. 이는 서브루틴이 단 하나의 인수를 취하거나 객체 지향 모듈에서 `$self` 인수를 처리하는 데 특히 일반적이다.


```perl
my $x = shift;
```


서브루틴은 명명된 인수를 시뮬레이션하기 위해 `@_`를 해시에 할당할 수 있다. 이는 세 개 이상의 매개변수를 가질 가능성이 있는 서브루틴에 대해 Perl Best Practices에서 권장된다.


```perl
sub function1 {
    my %args = @_;
    print "'x' argument was '$args{x}'\n";
}
function1( x => 23 );
```


서브루틴은 값을 반환할 수 있다.


```perl
return 42, $x, @y, %z;
```


서브루틴이 `return` 문을 통해 종료되지 않으면, 서브루틴 본문 내에서 마지막으로 평가된 표현식을 반환한다. 반환 값의 배열과 해시는 인수와 마찬가지로 스칼라 목록으로 확장된다.

반환된 표현식은 서브루틴의 호출 컨텍스트에서 평가된다. 이는 부주의한 사람들을 놀라게 할 수 있다.


```perl
sub list { (4, 5, 6) }
sub array { @x = (4, 5, 6); @x }

$x = list; # 6 반환 - 목록의 마지막 요소
$x = array; # 3 반환 - 목록의 요소 수
@x = list; # (4, 5, 6) 반환
@x = array; # (4, 5, 6) 반환
```


서브루틴은 `wantarray` 함수를 사용하여 호출 컨텍스트를 파악할 수 있다.


```perl
sub either {
    return wantarray ? (1, 2) : 'Oranges';
}

$x = either; # "Oranges" 반환
@x = either; # (1, 2) 반환
```

### 익명 함수

## 정규 표현식
펄 언어에는 정규 표현식(RE, 또는 regexes)을 작성하기 위한 특수화된 구문이 포함되어 있으며, 인터프리터에는 문자열을 정규 표현식과 일치시키는 엔진이 포함되어 있다. 정규 표현식 엔진은 퇴각검색 알고리즘을 사용하여, 단순한 패턴 매칭에서 문자열 캡처 및 대체까지 기능을 확장한다. 정규 표현식 엔진은 헨리 스펜서가 작성한 정규 표현식에서 파생되었다.

펄 정규 표현식 구문은 원래 유닉스 버전 8 정규 표현식에서 가져왔다. 그러나 펄의 첫 번째 릴리스 이전에 분기되었으며 그 이후로 훨씬 더 많은 기능을 포함하도록 성장했다. PHP, 루비, 자바, 마이크로소프트의 닷넷 프레임워크, 아파치 HTTP 서버와 같은 다른 많은 언어와 응용 프로그램이 이제 펄 호환 정규 표현식을 POSIX 정규 표현식보다 채택하고 있다.

정규 표현식 문법은 역사적으로 매우 간결하다. 초기 정규 표현식 방언은 글로브보다 표현력이 약간 더 많았고, 문법은 표현식이 일치하는 텍스트와 유사하도록 설계되었다. 이는 지원되는 몇 가지 주장을 표현하기 위해 단일 구두점 문자나 한 쌍의 구분 문자를 넘지 않도록 하는 것을 의미했다. 시간이 지남에 따라 정규 표현식의 표현력은 엄청나게 성장했지만, 문법 설계는 결코 수정되지 않았고 계속해서 구두점에 의존하고 있다. 결과적으로 정규 표현식은 난해하고 매우 밀집될 수 있다.

### 사용

`m//` (매치) 연산자는 정규 표현식 매치를 도입한다. (여기 모든 예시에서처럼 슬래시로 구분되는 경우, 간결성을 위해 선행하는 `m`은 생략될 수 있다. 다음 모든 예시에서처럼 `m`이 있는 경우, 슬래시 대신 다른 구분 기호를 사용할 수 있다.) 가장 간단한 경우, 다음과 같은 표현식은


```perl
$x =~ /abc/;
```


문자열 `$x`가 정규 표현식 `abc`와 일치하는 경우에만 참으로 평가된다.

반면에 `s///` (대체) 연산자는 검색 및 대체 작업을 지정한다.


```perl
$x =~ s/abc/aBc/; # b를 대문자로
```


정규 표현식의 또 다른 용도는 `split` 함수의 구분 기호를 지정하는 것이다.


```perl
@words = split /,/, $line;
```


`split` 함수는 정규 표현식과 일치하는 것에 의해 분리된 문자열 부분들의 목록을 생성한다. 이 예제에서는 한 줄이 쉼표로 구분된 부분들의 목록으로 나뉘고, 이 목록은 `@words` 배열에 할당된다.

### 문법

#### 수정자

펄 정규 표현식은 수정자를 사용할 수 있다. 이들은 표현식의 의미를 수정하는 단일 문자 접미사이다.


```perl
$x =~ /abc/i; # 대소문자 구분 없는 패턴 매치
$x =~ s/abc/aBc/g; # 전역 검색 및 대체
```


정규 표현식의 간결한 문법은 이해하기 어렵고 암호처럼 만들 수 있기 때문에, 프로그래머가 더 읽기 쉬운 정규 표현식을 작성하는 데 도움을 주기 위해 펄에 `/x` 수정자가 추가되었다. 이 수정자는 프로그래머가 정규 표현식 내부에 공백과 주석을 추가할 수 있게 한다.


```perl
$x =~ /
 a   # 'a' 매치
 .   # 임의의 문자
 c   # 그리고 'c' 문자
 /x;
```


#### 캡처

정규 표현식의 일부는 괄호로 묶을 수 있으며, 일치하는 문자열의 해당 부분은 캡처된다. 캡처된 문자열은 순차적인 내장 변수 `$1, $2, $3, …`에 할당되며, 캡처된 문자열 목록은 일치의 값으로 반환된다.


```perl
$x =~ /a(.)c/; # 'a'와 'c' 사이의 문자 캡처
```


캡처된 문자열 `$1, $2, $3, …`는 나중에 코드에서 사용할 수 있다.

펄 정규 표현식은 `/e` 수정자를 사용하여 캡처된 일치 항목에 내장 또는 사용자 정의 함수를 적용할 수도 있다.


```perl
$x = "Oranges";
$x =~ s/(ge)/uc($1)/e; # OranGEs
$x .= $1; # 이전 문장에서 일치한 내용으로 $x를 추가: OranGEsge
```


## 객체

펄에서 객체 지향 프로그래밍 코드를 작성하는 방법은 여러 가지가 있다. 가장 기본적인 방법은 "축복받은(blessed)" 참조를 사용하는 것이다. 이것은 모든 유형의 참조를 주어진 패키지에 속하는 것으로 식별하여 작동하며, 패키지는 축복받은 참조에 대한 메서드를 제공한다. 예를 들어, 2차원 점은 다음과 같이 정의할 수 있다.


```perl
sub Point::new {
    # 여기서 Point->new(4, 5)는 $class가 'Point'가 되도록 한다.
    # 이는 서브클래싱을 지원하는 변수이다 (perloop manpage 참조).
    my ($class, $x, $y) = @_;
    bless [$x, $y], $class;  # 암시적 반환
}

sub Point::distance {
    my ($self, $from) = @_;
    my ($dx, $dy) = ($$self[0] - $$from[0], $$self[1] - $$from[1]);
    sqrt($dx * $dx + $dy * $dy);
}
```


이 클래스는 `new()`를 호출하여 인스턴스를 생성하고, 해당 인스턴스에 `distance`를 호출하여 사용할 수 있다.


```perl
my $p1 = Point->new(3, 4);
my $p2 = Point->new(0, 0);
print $p1->distance($p2); # 5를 출력
```


많은 최신 펄 애플리케이션은 Moose 객체 시스템을 사용한다. Moose는 메타 객체 프로토콜인 Class::MOP 위에 구축되어 모든 Moose 사용 클래스에 대한 완전한 자기 성찰 기능을 제공한다. 따라서 간단한 API를 사용하여 클래스의 속성, 부모, 자식, 메서드 등을 질문할 수 있다.

**Moose 클래스:**
* 클래스는 0개 이상의 속성을 가진다.
* 클래스는 0개 이상의 메서드를 가진다.
* 클래스는 0개 이상의 슈퍼클래스(일명 부모 클래스)를 가진다. 클래스는 슈퍼클래스에서 상속한다.
* 클래스는 0개 이상의 역할을 수행하며, 서브클래싱 없이 미리 정의된 기능을 클래스에 추가할 수 있는 기능을 추가한다.
* 클래스는 생성자와 소멸자를 가진다.
* 클래스는 메타클래스를 가진다.
* 클래스는 0개 이상의 메서드 수정자를 가진다. 이러한 수정자는 자체 메서드, 조상으로부터 상속된 메서드, 또는 역할에 의해 제공되는 메서드에 적용될 수 있다.

**Moose 역할:**
* 역할은 클래스가 수행하는 것으로, 다른 객체 지향 프로그래밍 언어의 믹스인 또는 인터페이스와 다소 유사하다. 믹스인 및 인터페이스와 달리 역할은 개별 객체 인스턴스에 적용될 수 있다.
* 역할은 0개 이상의 속성을 가진다.
* 역할은 0개 이상의 메서드를 가진다.
* 역할은 0개 이상의 메서드 수정자를 가진다.
* 역할은 0개 이상의 필수 메서드를 가진다.

### 예시

Moose의 MooseX::Declare 확장자를 사용하여 작성된 클래스의 예시:


```perl
use MooseX::Declare;

class Point3D extends Point {
    has 'z' => (isa => 'Num', is => 'rw');

    after clear {
        $self->z(0);
    }
    method set_to (Num $x, Num $y, Num $z) {
        $self->x($x);
        $self->y($y);
        $self->z($z);
    }
}
```


이것은 `Point3D`라는 클래스로, Moose 예제에서 설명된 `Point`라는 다른 클래스를 확장한다. 이 클래스는 기본 클래스에 새로운 속성 `z`를 추가하고, `set_to` 메서드를 재정의하며, `clear` 메서드를 확장한다.

## 각주

## 외부 링크
* Perl 튜토리얼
* 약 2시간 30분 만에 펄 배우기
* PerlMonks 펄 지식과 코딩 팁 공유에 전념하는 커뮤니티.

분류:펄