저번에 LIKE 연산자를 배웠습니다. 이번에는 조금 더 복잡한 패턴 매칭에 대해서 다뤄보겠습니다.

 

 

[관련글]

LIKE 연산자 알아봅시다.

 

 

 눈치 채신 분도 있으실지 모르겠습니다. 자바에서 파싱할 때, 정규 표현식을 자주 쓰는데요. mysql은, REGEXP 라는 것으로, 정규식을 사용할 수 있습니다.

 

 


 처음과 끝은 각각 ^과 $로 표현할 수 있어요. 예를 들어서, '^a'라면, a로 시작하는 패턴입니다. 그리고 'E$'이라면, E로 끝나는 패턴입니다. 그러면 '^eat$'은 무엇을 의미할까요? "eat"를 찾으라는 거겠네요. 그리고, .은 임의의 문자를 의미하는데요. '^...$'은, 길이가 3인 문자열이 패턴에 매칭된다는 이야기입니다.

 

 

 이 쿼리를 수행해 봅시다. 그러면 문자열이 시작하고 임의의 문자가 3개 나오고 끝납니다. 그 말은, "Tom"이나 "Bob"도 matching이 된다는 소리일 거에요.

 

 

 

 결과는, _name 필드의 문자열 길이가 3인 것들만 출력됩니다.

 

 


 그런데, 우리는 _name이 모음으로 시작하는 것들을 구한다고 해 봅시다. LIKE를 쓰면 대충 10개의 조건절을 and로 연결하거나, 아니면 left 함수로 1개의 문자열을 가져온 것이, IN에 속해있는지. 등등 조금 복잡하게 쿼리를 작성해야 할 거에요.

 

 [...] 패턴은 ...에 속하는 문자 집합이 패턴에 걸린다는 의미인데요. 예를 들자면 이런 경우를 봅시다.

 

 

 이 쿼리는 무엇을 의미할까요? 일단 문자열이 시작했다는 ^가 들어와 있고, []가 있네요. 안에 것을 보니까 aAeE가 있는데, 첫 문자의 가능 집합이 a, A, e, E라는 것입니다. 즉, _name 필드가 이 4개의 문자로 시작하는 레코드들을 모두 출력하라는 의미입낟.

 

 

 쿼리의 결과는 다음과 같습니다. 그러면, a, A, e, E라는 문자가, 첫 번째에도 나오고 두 번째에도 나와야 하는 경우는 어떻게 작성해야 할까요? 이 때, {n}이라는 키워드를 씁니다. 해당 패턴이 n회 반복된다.

 

 

 이 문장의 의미는, string이 시작하고 나서, a나 A나 e나 E가 2회 반복되어야 한다는 것입니다. 즉, aa~나 aA~나 ae~나 aE나, ... , EE가 해당 패턴에 걸릴 거에요. 그러면 저 셋 중에는, eat가 있는 필드만 걸리겠네요.

 

 

 하핫. 만약에 1회 이상 2회 미만 그러한 패턴이 나타나는 패턴이 참이 되게 하고 싶다면 어떻게 하면 될까요? {n,m}을 쓰시면 됩니다. 이것은 패턴이 n회 이상, m회 이하 등장한다는 의미입니다. Arie, Asia, eat 셋 중에, 다음 패턴을 만족하는 것이 몇 개나 있을까요?

 

 

 일단, a나 A나 e나 E가 나타나는 패턴이 최소 1회, 최대 1회 반복이 되고, 임의의 문자가 하나 나오면 A?나 A?나 e?나 E?가 저것과 매치가 될 거에요. 그러면, 저 셋 중에서 만족하는 것이 없어요. 그런데, 아래와 같은 경우에는 이야기가 달라집니다.

 

 

 보시면 패턴이 1회 이상 2회 이하 반복되고, 임의의 문자 하나가 들어오고 끝나면 만족을 하는데요.

 

 

 eat는 만족합니다. e가 aAeE 패턴에 만족하고, a 또한 aAeE 조건에 만족합니다. 2회 반복되었고, 다음에 t는 임의의 문자 중 하나입니다. 개행을 제외한. 따라서 eat가 있는 레코드만 출력이 됩니다. [^...]은 무엇을 의미할까요? ...에 속하지 않는 문자 집합을 의미합니다.

 

 

 위 쿼리를 실행해 봅시다. 그러면 문자열이 시작하고, 첫 번째 문자가 a나 A가 아니여야 합니다. _name 필드가 그러한 것만 고르는 query입니다. 한 번 실행을 해 봅시다.

 

 

 Asia랑 Anie는 빠졌음을 알 수 있어요.

 

 


 *과 +이 남았네요. *은 패턴이 0번 이상, +은 1번 이상 나타난다는 것을 의미합니다. 예를 들어서, 다음과 같은 것을 생각해 봅시다.

 

 

 이것은 문자열이 시작했을 때, A,a,E,e가 최소 0회 이상 나오는 패턴과 매칭이 됩니다.

 

 

 실행 결과는 아래와 같이 나옵니다. 시작 문자가 어느 것이던 상관 없다는 겁니다. 그런데 +가 붙으면 이야기가 달라지는데요. 이것은 최소 1회 이상 문제의 패턴이 반복되어야 한다는 겁니다.

 

 

 쿼리를 이렇게 작성해 봅시다.

 

 

 그러면 A나 a나 E나 e로 시작하는 것들만 나올 거에요. 마지막으로, |가 있는데요. 이것은 or를 의미합니다.

 

 

 다음 쿼리는 A로 시작하거나, B로 시작하는 패턴을 찾으라는 겁니다.

 

 

 결과는 3개의 row가 리턴됩니다.

 

 


 그러면 _name이 모음으로 시작하면서, 모음으로 끝나는 것들은 어떻게 구하면 좋을까요? 일단, 저는 다음과 같은 쿼리를 수행해 보겠습니다. 당연하게도, 길이가 1짜리면서 모음인 데이터를 추가한 겁니다.

 

 

 다음에, 쿼리를 생각해 봅시다. 일단 문자열이 시작해야 하고, [aeiouAEIOU] 라는 pattern이 들어와야 할 겁니다. 다음에 임의의 문자가 0개 이상 오고, [aeiouAEIOU] 패턴이 온 다음에 끝나야 겠지요.

 

 

 그러면, 이런 식으로 작성할 수 있을 겁니다. 그런데, 이 경우 길이가 1인 데이터는 매칭이 되지 않을 겁니다.

 

 

 결과를 확인해 보면, "A"라는 것은 matched가 되지 않았음을 알 수 있어요. 그러면 어떻게 작성하면 좋을까요?

 

 

 이렇게 작성하면 어떻게 수행이 될까요? 일단, 첫 패턴이 모음인지 검사합니다. 그 다음에 괄호 안으로 들어갈 건데요. 판단 state를 그려보면 아래와 같습니다.

 

 

 보시면 모음이 나온 후에 바로 Terminate가 되거나, 아니면 임의의 문자가 0회 이상 나온 후에, 모음으로 끝나는 패턴만 regexp에 걸리게끔 하고 있어요. 조금 어려운 예제였습니다. 그러면, 모음으로 시작하거나, 모음으로 끝나는 건 어떻게 작성하면 좋을까요?

 

 

 Conditions를 괄호로 묶고 |를 붙이면 됩니다. 어떤 조건인가요? ^[모음들]이거나, [모음들]$이겠지요. 이 둘을 괄호로 묶어준 다음에 |로 연결해 주시면 됩니다. 정규 표현식을 연습하는 사이트는 여러 곳이 있습니다. 거기에서 연습해 보셔도 좋을 듯 싶습니다.