본문으로 이동

예제로 배우는 AWK/루프

위키책, 위키책

루프의 개념

[+/-]

루프란 컴퓨터 프로그램에서 일련의 작업을 반복하는 것을 의미합니다.

컴퓨터 프로그램의 강점은 이 루프에 있다고 할 수 있습니다. 인간은 단순하고 반복적인 작업을 오랫동안 많이 하는 것이 지루하고 힘든 반면에 컴퓨터는 이러한 종류의 일을 쉽고 빠르게, 또 정확하게 처리하기 때문입니다.

예를 들어 인간에게 1부터 100만까지의 자연수를 순서대로 종이에 쓰도록 명령한다고 생각해 봅시다. 아무리 인내심이 좋은 사람이더라도 10000까지도 못 쓰고 지쳐버리고 말 것입니다.

그러나 컴퓨터는 다음과 같은 문장으로 명령만 해주면 이러한 일을 간단하게 해냅니다.

(1부터 1000000까지) {숫자를 출력하라}

컴퓨터에게 루프의 형태로 작업을 하도록 명령을 하려면 크게 두 가지를 작성해야 합니다.

하나는 루프 작업의 범위를 설정해주는 것입니다. 위의 문장에서 ( )에 해당하는 부분입니다. 예시에서는 1~1000000까지의 범위 내에서만 루프를 하도록 했습니다. 즉 같은 행동을 100만번 하라는 것이죠.

두번째는 1루프당 해야할 "행동"을 설정해주는 것입니다. 예시문에서 { } 부분에 해당하는 것으로, 여기에서는 "출력하라"는 명령을 내렸습니다. 행동의 종류는 여러 가지가 있을 수 있습니다. 대표적인 행동으로는 사칙연산이 있습니다. 예를 들어 100만개의 숫자를 모두 더하는 행동을 하도록 만들 수 있습니다.

(1부터 1000000까지) {숫자들을 더하라}

루프의 개념에 혼란이 생기지 않도록 한 가지 더 말씀드리자면, 루프는 단순히 같은 작업을 반복하는 것이 아니라 "정형화된 일"을 반복하는 것을 의미합니다. 아래의 두 문장을 비교해 보십시오

(1부터 1000000까지) { 1 출력하라 }
(1부터 1000000까지) { 숫자를 출력하라 }

첫 번째 문장의 경우 완전하게 같은 작업을 100만번 하는 것입니다. 인간에게 시킨다면 1을 100만번 쓰게 하는 것이죠. 두 번째 문장의 경우 1부터 100만까지의 숫자를 순서대로 쓰는 것입니다. "쓴다"는 행위 자체는 정형화된 일이지만, 쓰는 대상이 달라졌음을 알 수 있습니다. 이처럼 루프는 완전히 동일한 일의 반복이라기 보단, 동일한 형식의 반복이라고 이해하는 것이 좋습니다. 물론 완전하게 동일한 일 역시도 동일한 형식을 갖고 있기 때문에 루프의 의미에 포함됩니다.

AWK에서 루프의 예시

[+/-]

AWK에서는 루프를 만드는 대표적인 방법으로 for문을 이용하는 것이 있습니다.

	for (initial ; condition; increment) {
		action
	}

for 다음에 있는 ( ) 부분이 루프의 범위이고 { } 부분이 루프동안 해야 할 일입니다. 소스를 보면 아시겠지만 AWK에서는 for를 이용해 범위를 설정할 때 세 가지 정도로 구분해서 쓰게 됩니다. 처음 initial부분은 초기값을 지정해주는 것입니다. 첫 번째 루프가 어디에서 시작하는지를 정해준다고 보시면 됩니다. 두번째 condition부분은 루프의 범위를 지정해주는 것입니다. 다르게 말하면 루프가 실행될 조건을 정하는 것으로 루프의 마지막값을 정한다고 보셔도 됩니다. 마지막 increment부분은 초기값에서 끝값으로 이동할 때의 방법을 지정하는 것입니다. 예를 들어 1~100처럼 1씩 늘어나며 이동할 수도 있고, 반대로 100~1처럼 1씩 감소하면서 이동할 수도 있습니다.

구체적인 예를 통해서 위의 개념을 확인하도록 하겠습니다. 1부터 1000000까지를 출력하는 AWK 프로그램을 만들어보겠습니다.

BEGIN {
	for (i = 1 ; i <= 1000000; i++) {
		print i;
	}
}

위의 소스를 실행하면 1~1000000의 숫자가 차례대로 출력됩니다. 1에서 시작하여, 1000000보다 작거나 같은 범위에서, 1씩 증가하며 이동하였고 그때마다 i값을 출력하는 행동을 하는 것입니다. AWK에서는 1씩 증가한다는 것을 i++라고 표현합니다.

만약 1만 100만번 출력하고 싶다면 어떻게 해야 할까요?

BEGIN {
	for (i = 1 ; i <= 1000000; i++) {
		print 1;
	}
}

행동을 작성하는 곳에서 i를 1로 바꾸어주기만 하면 됩니다. 언뜻 보면 i가 증가하고 있는데 1이 출력되는 것과 무슨 상관을 갖고 있는 것인지 이해가 안 갈 수 있습니다. 그러나 사실 컴퓨터 속에서는 100만번의 루프동안 꾸준히 i를 증가시키고 있습니다. 단지 사용자의 눈에 보이지 않게 하고 있을 뿐입니다. 우리의 눈에는 모두 동일한 1을 출력하고 있는 것이지만 컴퓨터의 입장에서는 'i가 n일 때 n번째 루프에서의 1'인 것입니다. 이를 확인하고 싶으면 다음과 같이 만들어보면 됩니다.

BEGIN {
	for (i = 1 ; i <= 1000000; i++) {
		print i, 1;
	}
}

다른 예를 하나 더 살펴보겠습니다. 아래는 1부터 100까지를 더한 값을 출력하는 프로그램입니다.

BEGIN {
	for (i= 1 ; i<=100 ; i++) {
		total = total + i;
	}

	print total;
}

위와 같이 프로그램을 짜면 total이라는 변수에 1, 2, 3, .. 100의 순서로 값이 더해집니다. [1]

위 프로그램을 실행시키면 최종적인 출력값 5050이 모니터에 나타나게 됩니다. 혹시 컴퓨터가 정말 루프 작업을 통해서 계산을 하고 있는지 확인하고 싶으신 분은 다음과 같이 작성하고 실행해 보세요. print 명령을 루프 속으로 포함시키면 됩니다.

BEGIN {
	for (i= 1 ; i<=100 ; i++) {
		total = total + i;
		print total;
	}	
}

위의 프로그램을 실행시키면 컴퓨터는 1루프 동안 더하기 작업과 출력 작업을 하게 됩니다. 눈치채셨겠지만 한 번의 루프에서 하는 행동이 꼭 하나일 필요는 없습니다.

루프는 프로그램에 있어서 매우 유용하고 강력한 기능입니다. 루프를 잘 사용하면 방대한 양의 계산도 매우 간단하게 해낼 수 있습니다.

주석

[+/-]

<references>

  1. total = total + i 라는 식이 일반적인 수학식에서는 말이 안되지만 컴퓨터 프로그램의 경우에는 =이 "같다"는 의미가 아니고 "대입한다"는 의미로 사용됩니다. 즉 앞의 식을 말로 표현하자면 total이라는 변수에 기존의 total값에서 i를 더한 만큼의 값을 다시 대입하라는 것입니다. AWK에서는 같다는 의미를 쓰고 싶을 때는 ==를 씁니다.