이명헌 경영 스쿨
[펄] 펄의 변수와 스케일라(scalar): 문자열 처리 그리고 간단한 조절문
펄의 단수 명사
이명헌 [ 2001-10-2 ]

펄에는 크게 세 가지 변수가 있습니다. 다른 프로그래밍 언어보다 변수형에 있어서 엄격하지 않기 때문에 이해하기가 훨씬 쉽고 실제 코딩도 아주 편리하고 간단합니다.

명사와 변수

프로그램 언어를 배우는 것은 외국어를 배우는 것과 많은 유사점이 있습니다. 언어마다의 문화가 있습니다. 언어를 사용하는 커뮤니티가 존재합니다. 그밖에 실제 언어 자체로서도 많은 공통점이 있습니다.

난삽(?)하게 쓰여진 것으로 악명 높은 펄의 '교과서', "Programming Perl"(일명 Camel Book; 펄을 만든 Larry Wall氏가 직접 쓴 책입니다)을 보면 우리가 사용하는 일상 언어와 프로그래밍 언어 사이의 유사점을 들어 설명하는 방식이 곧잘 등장합니다. 래리 월氏는 정말 언어학자(linguist)였기 때문에 그런 경향이 더 두드러지는 것 같습니다. 예를 들어 이런 얘기가 나옵니다.

소년변수는 '명사'에 해당하고, 함수는 '동사'에 해당되니다. 펄에서 변수 이름을 만들 때, 앞에 특수기호 ($, @, %)를 붙여서 만드는데 이것은 자연어의 '관사'에 해당됩니다.

중요한 것은 명사니 동사니 하는 게 아니고, 펄은 독특하게도 변수 이름 앞에 특수 문자를 붙여서 변수의 형을 결정한다는 것입니다. 다른 프로그래밍 언어는 거의 다 변수 이름 앞에 특별한 기호가 붙지 않습니다. 알파벳이나 숫자를 일정한 규칙에 맞게 배열하면 변수 이름으로 사용할 수 있으며 변수의 형(type; 정수형, 실수형, 불리언형,.)은 선언(declaration)이라는 과정을 거쳐서 결정하는 게 보통입니다.

펄은 독특하게도 변수 이름 자체에 특수기호를 붙여서 선언 없이 변수 이름이 곧바로 형을 나타내게 되어 있습니다. 영어의 관사처럼 그 변수의 특징을 이름만 보고도 알 수 있습니다. a boy, a girl 등이 "a" 라는 관사를 통해서 단수명사로 파악되는 것처럼, 펄의 변수 역시 변수 앞에 붙은 기호를 통해 형을 알 수 있습니다. 펄의 변수 중 '단수'에 해당하는, 즉 한 개짜리 무엇을 담는 변수를 스케일라(scalar)라고 합니다. 스케일라 변수는 변수 이름 앞에 $(달러표시)를 붙여서 만듭니다. $가 scalar 의 "s"와 유사하다는 것으로 기억하면 됩니다. 예를 들어 다음은 여러 스케일라 변수에 숫자나 문자, 문자열을 할당한 것입니다.

$a = 13;
$b = 'a';
$c = '25';
$d = "xyz";
print $a,$b,$c,$d;

펄의 변수는 그 변수 이름에서 이미 형이 드러나기 때문에 따로 선언하지 않습니다. 달러 표시만 붙어있으면 숫자나 문자 한 개를 담는 스케일라 변수가 됩니다. 여기에 대해서는 C 나 자바, 파스칼을 쓰던 사람들은 언어가 너무 규칙없이 어지럽다고 비판하기도 하지만 한편에서는 이런 점이 펄의 매력이라고 얘기합니다. 각자의 호불호는 있겠지만 펄은 상대적으로 간편하고 자유롭습니다.

또 하나, 스케일라 변수에는 숫자나 문자, 문자열이 다 담길 수 있다는 점도 주의하세요. 펄의 변수는 형(type)에 엄격하지 않습니다. 다른 언어, 이를테면 C나 자바, 또는 파스칼 등은 변수형이 펄에 비해 훨씬 더 엄격합니다. "strongly typed language"입니다. 어느 쪽이 더 좋은가에 대해서 여러 의견이 있습니다만 펄은 조금 더 분방한 쪽이라고 생각하면 됩니다.

스케일라 변수에 담을 수 있는 것에는 숫자, 문자 외에도 reference(C언어의 포인터와 비슷한 것으로 생각하시면 됩니다)와 객체가 있습니다. 레퍼런스나 객체에 관한 내용은 까다로운 편이기 때문에 여기서는 설명하지 않습니다.

단수는 스케일라라고 했습니다. 그렇다면 복수는 무엇일까요?
펄에서의 복수는 배열(Array)이라고 합니다. array의 앞글자처럼 @를 변수 이름 앞에 붙여서 사용합니다. 바꿔 얘기하면 스케일라를 모아 놓은 것이 배열입니다.

@a = (3, 2);
@b = 5;
@c = ("abc", 34, '21');
print @a; print @c;

펄은 각 구문을 세미콜론으로 구분합니다. 끝에 세미콜론 ;이 나오면 다음 구문이 시작되는 것으로 파악합니다. 펄의 주석문(comment; 프로그램 실행과 관계없는, 설명을 위한 구문)은 #으로 시작합니다. # 기호 다음의 내용은 컴파일 시에 무시합니다.

마지막 펄의 변수형은 해쉬(hash; associative array)입니다. 해쉬와 배열에 관해서는 다음 글에서 아주 자세하게 다룰 것입니다.

정리하면, 펄의 명사, 즉 변수에는 세 가지 종류가 있습니다.

  • 스케일라 변수: $로 시작
  • 배열 변수: @로 시작
  • 해쉬 변수: %로 시작

이제, 스케일라 변수부터 자세하게 알아 봅시다.

스케일라(Scalar)

위에서 스케일라는 한 개짜리 무엇이라고 했습니다. 숫자(number)가 되었든 문자(character)가 되었든 또는 문자열(string)이 되었든 한 개짜리는 다 스케일라 변수에 담을 수 있습니다.

숫자에서 특기할 만한 것으로는 '0'으로 시작하는 것은 8진수를 나타내고, '0x'로 시작하는 것은 16진수, '0b' 로 시작하는 것은 2진수를 나타낸다는 것이 있습니다. 다음은 모두 10진수로 255인 값들을 스케일라 변수에 할당한 것입니다.

$octal = 0377; # 8진수 377입니다.
# 10 진수로 고치면 (3*(8^2)) + (7*8) + 7 = 255
$hexa = 0xff; # 16진수 ff 입니다. 역시 10 진수로는 255
$binary = 0b11111111; # 2진수 11111111 입니다.
$decimal = 255;

문자열(string) 만들기

펄은 문자열 처리에 있어서 최강으로 알려진 언어입니다. 아주 복잡한 얘기들이 많습니다. 여기서는 스케일라 변수와 관계되는 간단한 것들만 알아보고 넘어갑시다.

문자열 표현 방식(literal representation of strings)에는 두 가지가 있습니다. 다음 두 가지 방식에 의해 표현된 것은 문자열로 파악합니다.

문자열첫째는 작은 따옴표로 묶인 문자들입니다. (single-quoted string literals)

'a'
''
'abc'
'\'
'\t\n'

이들 모두 문자열입니다. 스케일라 변수에 할당하면,

$a = 'abc';
$b = 'what do you want?';

두 번째로는 큰 따옴표로 묶인 문자들입니다. (double-quoted string literals)

"a"
"abc"
"\tmerong"

역시 스케일라 변수에 같은 방식으로 할당됩니다.

$mystring = "abc";
$bb = "xyz\n";

왜 똑같은 기능을 하는 것을 두 가지나 만들어 놨을까요? 둘은 차이가 있습니다. 큰 따옴표로 묶는 경우 백슬래쉬 탈출문자(\로 시작하는 여러가지 특수기능 문자)와 "variable interpolation"이 일어난다는 점에서 다릅니다. 이게 무슨 의미이냐면요.

백슬래쉬로 시작하는 탈출문자가 프로그래밍에서 널리 쓰이고 있습니다. 예를 들어, \n은 줄바꿈을 뜻하고, \t는 탭을 뜻합니다. 이런 백슬래쉬 탈출문자들이 작은 따옴표내에서는 아무 의미를 갖지 못합니다.

'abc\n'

이것은 그냥 a, b, c, \, n 이라는 다섯개의 문자로 이뤄진 문자열일 뿐입니다.

$single = 'abc\n';
print $single;

이것을 실행시키면 5개의 문자가 출력될 뿐입니다.

반면,

$double = "abc\n";
print $double;

위 코드를 실행하면 abc가 찍힌 다음 줄을 바꿔서 커서가 깜박거리게 됩니다. \n라는 특수한 의미를 가진 문자가 큰 따옴표 안에서는 특별한 의미로 쓰이기 때문입니다. 마찬가지로 특수한 의미를 갖는 문자를 그 문자 고유의 의미로 사용하기 위해서는 백슬래쉬를 이용해서 '탈출'을 해줘야 하는데 이러한 탈출이 큰 따옴표내에서만 의미가 있습니다. 예를 들어 달러 표시 $는 스케일라 변수를 만드는 데 사용되는 특수한 문자입니다. '진짜 달러' 표시로 쓰려면 이렇게 해야 합니다.

print "I have \$5.";

만약 $ 앞에 \를 써서 탈출하지 않으면 달러 표시가 뜨지 않습니다. 이런 것이 작은 따옴표에서는 안됩니다.

print 'I have \$5.';

이것을 출력해 보면 I have \$5.라고 출력됩니다. 백슬래쉬를 이용한 탈출이 안됩니다.

작은 따옴표보다는 큰 따옴표가 더 화려하게 생겼기 때문에 부가적인 기능이 있다고 이해를 하면 좋습니다. (저의 억지가 아닙니다. 곧 비슷한 논리가 여기저기서 등장합니다.)

다음으로 "variable interpolation"에 대해서 알아보죠.

$word = 'perl';
print "$word is fun!";

위 코드를 실행하면 perl is fun!이라고 출력됩니다. 이처럼 변수가 문자열 중간에 섞여 있을 때 그 변수의 값이 변수 이름을 대체하는 것을 "variable interpolation"이라고 합니다. 실제 코딩에서 매우 편리하게 활용할 수 있는 기능입니다.

그런데 작은 따옴표에서는 안됩니다.

$word = 'perl';
print '$word is fun !';

실행해 보면 어떻게 될 지 짐작이 되죠?

문자열 처리 연산자

문자열과 관계되는 연산자(operator)에는 크게 두 가지가 있습니다. 자주 쓰이는 것은 concatenation operator인 . 입니다. (점 한개) concatenation은 문자열을 합쳐주는 것입니다.
$abc = "hello" . " world";
print $abc;

이것은$abc = "hello world";와 마찬가지입니다.

C 언어 쓰는 사람들이 무척 부러워하는 것 중의 하나가 concatenation operator입니다.

또 하나는 x 입니다. 곱하기입니다.

$a = 'perl';
$b = $a x 3;
print $b;

$b에는 'perlperlperl'이 담기게 됩니다.반복입니다. 아주 속기 쉬운 퀴즈가 있습니다.

$aa = 5 x 4;
print $aa;

이것은 20이 출력되는게 아니라, 5555가 출력됩니다. 숫자 곱셈은 *이지 x가 아닙니다. x는 문자열을 반복하는 문자열 처리 연산자입니다.

스케일라 변수에 숫자도 담기고 문자도 담긴다면 이게 혼란을 일으키지 않을까라는 염려가 들 수 있습니다. 다행스럽게도 펄은 숫자와 문자열을 필요에 맞게 알아서 전환을 합니다. (automatic conversion between numbers and strings) 연산자를 보고 문자열로 취급하는게 맞으면 문자열로, 숫자가 맞으면 숫자로 취급합니다.

print "3" * "4";

이것은 12가 출력됩니다. 분명히 "3"도 문자열이고 "4"도 문자열이지만 연산자가 숫자 연산자인 *이기 때문에 알아서 변환합니다.

이렇게 펄은 문맥(context)에 맞게 자동으로 처리되는 것이 많습니다. 중요한 이야기입니다.
펄은 문맥에 따라 똑같은 문장이 전혀 다른 것을 의미할 수 있습니다. 이것이 바로 자연어의 특성이기도 합니다. 똑같은 "돈"이라는 단어라도 "돈을 벌다"에서의 "돈" 과 "머리가 돈 사람"에서의 "돈"은 전혀 다릅니다. 펄은 이런 자연어의 특징을 갖고 있습니다. 이것이 펄을 펄답게 만듭니다.

문자열 처리와 관련해서 펄은 다양한 함수와 기능들을 갖고 있습니다만, 그것은 별도의 문서에서 살펴보겠습니다. 여기서는 문자열 처리 관련 연산자에 ., x가 있다는 정도로만 해두겠습니다.

마지막으로 스케일라 변수의 할당에 대해서 한가지 더 얘기하고 이 글을 접겠습니다. 스케일라 변수에 값을 할당하는 것은 다른 프로그래밍 언어와 마찬가지로 =를 사용합니다.
$scalar = 13;

할당 연산자에는 = 외에 다른 것이 있습니다. C에서와 같은 binary assignment operator가 있습니다.

$count += 5;

이것은,

$count = $count + 5;

와 같은 의미입니다. 마찬가지로,

$multiply *= 2;

도 가능합니다.

이러한 binary assignment operator중에 가장 자주 쓰이는 것은,

$name .= " ";idiom

= 앞의 점에 주의하세요. 점은 concatenation, 문자열을 합쳐줍니다. 따라서 위의 구문은,

$name = $name . " ";

과 같은 의미로, $name 변수 값에 스페이스를 붙여서 다시 할당한다는 의미입니다. 이렇게 변수값에 변화를 줄 때 사용하는 것이 binary assignment operator입니다.

마지막 예는 꼭 기억해 두세요.

스케일라 변수와 관련있는 조절문

스케일라 변수와 관계되는 조절문에는 ifwhile이 있습니다. 다른 프로그래밍 언어에도 대부분 존재하는 것들입니다. 이것은 펄의 구문과 루프에서 자세히 다룰 것이므로 여기서는 가볍게 구경만 해봅시다. if부터 봅시다.

if (something) { do this }

위와 같은 형태로 쓰입니다. something이 '참' 이면 중괄호 안의 구문을 실행하라는 의미입니다.

자세한 얘기에 들어가기 전에 스케일라 변수와 관계되는 연산자 몇 개를 더 살펴보고 얘기를 풀어갑시다. 펄에도 여타 언어와 마찬가지로 비교연산자(comparison operators)가 있습니다. 크냐, 작으냐. 같으냐, 다르냐 등등을 비교하는 연산자입니다. C와 거의 대동소이합니다. 한 가지 차이점이 있다면 문자열의 경우 비교 연산자가 따로 있다는 것입니다. 라마북에 있는 표를 봅시다.

비 교 숫자(Numeric) 문자열(String)
같다 == eq
같지않다 != ne
작다 < lt
크다 > gt
작거나같다 <= le
크거나같다 >= ge

숫자인 경우와 문자열인 경우가 각각 따로 존재하기 때문에 주의해서 사용해야 합니다. 다음의 예를 보세요.

30 == 30 # 참이죠?
35 == 35.0 # 역시 참입니다.
'35' eq '35.0' # 거짓 입니다. 문자열 '35' 와 '35.0' 은 전혀 다른 것이죠

그러면 문자열에서 '크다', '작다', '크거나 같다'는 의미는 뭘까요.
아스키(ASCII) 값입니다. (아스키와 바이너리) 만약 첫글자의 아스키 값이 같다면 다음 글자를 비교합니다. 따라서 같은 문자로 시작된다면 글자 수가 많은 쪽이 더 '큰' 문자가 됩니다.

'floccinaucinihilipilification' gt 'merong' # 참이죠?
' ' gt '' # 공백 2칸은 공백 1칸보다 더 크니까 참

숫자에서와 문자열에서 비교 연산자가 다르다는 것을 꼭 주의하세요. ==eq를 잘못 사용하는 경우가 매우 많습니다. 그리고 이런 버그는 찾기 쉽지 않습니다. 흡사 ==를 써야 할 곳에서 =를 사용한 버그를 찾기가 힘든 것과 마찬가지입니다. 꼭 주의하세요.

이제 비교연산자를 if 구문에서 사용해 봅시다.

$myname = 'myonghon';
if($myname eq 'myonghon') { print "This code is obviously stupid";}

if 다음의 괄호안이 '참'이므로 print 구문이 실행됩니다.

위와 같은 경우는 참,거짓이 명백합니다만은 애매한 경우도 있습니다. 이것과 관계되는 것으로 "불리언 변수"(Boolean variables)가 있습니다. 참 아니면 거짓 두 가지 값 중 하나만 갖는 변수형을 불리언 변수라고 합니다. 퀴즈입니다.

$zero = '0';
if($zero) { print "This is true !" }

위의 코드를 실행하면 "This is true !"가 출력 될까요, 안 될까요?

위의 코드는 $zero가 '참'이면 print 구문이 실행됩니다. '거짓'이면 실행되지 않을 것입니다. 이 경우 $zero 변수는 불리언 변수가 됩니다. 참 또는 거짓 둘 중의 하나의 값을 갖습니다. 위의 코드를 실행하면 print 구문이 실행되지 않습니다. 왜 그럴까요?

어떤 경우에 '참'이고 어떤 경우에 '거짓'인지를 생각해 봅시다. 다음과 같은 규칙이 있습니다.

  1. 영(0)은 거짓이다. 그외 숫자는 모두 참.
  2. 빈문자열 ''은 거짓이다. 그외 문자열은 모두 참.
  3. 문자열 형태로 된 '0' 역시 숫자 0으로 취급해서 거짓이다. (이것을 주의하세요.)
  4. undef 값은 거짓이다. (undef는 변수에 아무것도 할당하지 않은 상태, 즉 아무것도 없는 상태를 얘기합니다.)

문자열 형태로 된 '0'도 숫자 0으로 취급되므로 위의 코드는 if() 안이 거짓이 되어서 "This is true !"가 출력되지 않습니다.

스케일라 변수와 관계되는 다른 조절문으로 while 구문이 있습니다. whilefor처럼 '루프'(loop)를 만들 때 사용합니다.

while (something) { do this endlessly }

something이 '참'인 한,(while something is true...) 중괄호 안의 구문을 무한히 반복한다입니다. 물론 빠져나오는 방법도 있습니다.
if하고는 구분해야 합니다. if는 참인 경우 중괄호 안의 구문을 한 번 실행하고 끝입니다만 while은 '루프'를 합니다. 계속 반복합니다.

예를 들어보면,

$count = 0;
while ($count < 10 ) {
$count += 1;
print "카운트는 $count 입니다\n";
}

정리해 봅시다. 스케일라 변수와 관계되는 조절문에는 if 구문과 while 루프가 있습니다. 여기에 관계되는 내용으로 비교연산자, 불리언 변수라는 것이 있었습니다. 그리고 문자열의 경우 비교연산자가 따로 존재한다는 사실도 중요한 내용입니다.

지금 계신 곳은: TECH > [펄] 펄의 변수와 스케일라(scalar): 문자열 처리 그리고 간단한 조절문