^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
지난 회에 보여드린 정규식이죠? 이는 다음과 같이 작성할 수도 있습니다.
^((([0-9]{1,2})|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]{1,2})|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))$
이것 말고 다른 정규식도 얼마든지 가능합니다. 사실 정규식에는 정답이란 게 없거든요. 아주 간단한 문제가 아니라면 말입니다. 우선 첫 번째 정규식부터 하나씩 뜯어볼까요?
맨 앞의 ^ 기호가 들어가야 하는 이유는 지난 회에서 설명드렸으므로 생략합니다. 이어서 두 개의 둥근 괄호가 나오고 | 기호에 의해 숫자들이 죽 나열되어 있습니다. |는 or이니까 [0-9]이거나, 즉 한 자리 아무 숫자이거나 [1-9][0-9]이거나 즉, 두 자리 아무 숫자이거나가 됩니다. 그 다음 1[0-9]{2}는 1로 시작하는 세 자리 숫자를 의미합니다. 역시 아무 숫자나 올 수 있습니다. 2[0-4][0-9]는 2로 시작하되 두 번째 자리는 0-4이고 세 번째는 아무 숫자나 올 수 있다는 의미입니다. 25[0-5]는 25로 시작하되 세 번째 자리는 0-5까지 올 수 있다는 의미입니다.
그 다음에 괄호가 하나 끝나고 마침표(그냥 마침표는 메타문자이므로 이스케이프 처리했습니다)가 오고 {3}에 의해 이같은 문자열이 3번 반복됩니다. 그 다음에 이어지는 역시 두 개의 둥근 괄호는 앞의 괄호와 똑같은 구조이니 설명 생략입니다.
이렇게 하나씩 뜯어서 살펴보니 쉽죠? 사실 역참조니 조건절이니 하는 게 들어가지 않는 이상 아무리 길어봐야 복잡해 보이는 것일뿐 별거 없습니다. 그럼 두 번째 정규식도 마저 볼까요?
[0-9]{1,2}는 한 자리 숫자이거나 두 자리 숫자이거나라는 의미입니다. [0-9]|[1-9][0-9]와 전적으로 같은 의미입니다. 그 뒤로는 똑같으니 역시 설명 생략입니다.