문자열 처리를 할 때 토큰화 시키는 것이랑 trim 등은 매우 많이 쓰게 됩니다. 이번 시간에는 postgresql에서 특정 문자를 기준으로, split_part라는 함수를 이용해서 토큰화 시키는 방법을 알아보겠습니다.

 


 

 먼저 3개의 인자를 받습니다. 원본 스트링, 그리고 delimeter 역할을 할 것 하나, 위치입니다. 저는 '-'를 기준으로 나누었기 때문에, a, b, c, d, efg, hi 순으로 나누어질 것이라는 것을 알 수 있습니다. 이 중 2번째는 b이므로 b가 출력되게 됩니다.

 

 

 정말 그런지 보니, 'b'가 출력됨을 알 수 있어요.

 

 

 다음에, 원본 문자열 'a-b-c-d-efg-hi'에서, '-'를 delimeter로 해서, 5번째 원소를 뽑으려고 합니다. 이 경우, a, b, c, d, efg, hi 순으로 뽑히게 될 겁니다. 5번째는 efg이므로, 'efg'가 출력됩니다.

 

 

 역시 어렵지 않게 예상할 수 있습니다.

 


 -가 붙으면 어떻게 될까요? 즉, 뽑을 위치가 음수이면 어떻게 될까요? 이 때에는 신기하게도, 뒤에서부터 거꾸로 보게 됩니다. '-'라는 문자를 delimeter로 삼는데요. -3이므로 뒤에서부터 3번째를 뽑게 됩니다. 뒤에서부터 보면, hi, efh, d, c, b, a 순으로 나가게 되는데요. 이 중 3번째는 d이기 때문에, 결과는 'd'가 출력됩니다.

 

 

 그러하다고 합니다.

 

 

 하나 더 질문. 'a-b-c-d-efg-hi--' 이런 건 어떨까요? '-'를 구분자로 하는데, 뒤에서부터 3번째를 뽑고 싶답니다. 어떻게 될까요? 이렇게 '-'가 연속해서 나오는 경우가 골때리는데요. 결과부터 보고 왜 이런 결과가 나왔는지 추정하는 게 좀 더 빠르겠네요.

 

 

 결과를 보니까 hi가 나왔는데요. hi 근방을 보면 'hi--'입니다. 이를 조금 더 풀어서 쓰면 hi, 구분자, 빈 문자열, 구분자, 빈 문자열 순으로 나온 것인데요. 실제로, -1, -2를 3번째 인자에 넣어보면 그냥 빈 문자열만 나오게 됩니다. 그런데, -3을 3번째 인자로 넣었을 때, hi가 아니라 d가 나오게 하려면 어떻게 해야 할까요? 이 말인 즉슨, 뒤에나 앞에 오는 '-'를 제거하고, 연속된 '-'를 하나의 '-'로 만들라는 의미와 동치인데요.

 

 trim과 regexp_replace 등으로 손쉽게 처리할 수 있습니다.

 

 먼저, trim으로 앞과 뒤에 나오는 모든 '-'를 제거합니다. trim(both A from B)는 문자열 B에 양 옆으로 나오는 A를 모두 제거하라는 의미입니다. 그러면, trim으로 인해, '-a---b-c--d--efg-hi---'는 'a---b-c--d--efg-hi'가 될 겁니다. 그 다음에 -가 하나 이상 나오는 패턴에 대해서 모두 '-'로 replace를 합니다. 이것은 regexp_replace로 처리하면 됩니다.

 

 

 그러면 요래 나오겠죠? 이 결과를, split_part의 1번째 인자에 넣어버리면 됩니다.

 

 

 1번째 인자는 regexp_replace와 trim에 의해 'a-b-c-d-efg-hi'가 되었습니다. 이제 여기서 '-'를 delimeter로 구분지었을 때 뒤에서부터 3번째 위치에 있는 문자열만 보면 되는데요. 'd'입니다. 따라서, 'd'가 결과로 나오게 됩니다.

 

 

 그렇게 나왔음을 확인할 수 있습니다.

 

 


 추가 보너스. split_part의 처음 first token이랑 마지막 last token은 어떻게 뽑으면 될까요? 사실, 처음과 마지막은 trailing이라던지, following delimeter를 제거한다면 굳이 regexp로 처리할 필요가 없습니다.

 

 

 따라서 위와 같이 처리해 주면 편리하게  처리 가능합니다. 중요한 것은 trim으로 delimeter가 초반, 혹은 끝에 여러 개 붙어 나오는 패턴을 제거했다는 점입니다. 이것 외에는 3번째 인자에 1을 넣으면 처음 1번째가, -1을 넣으면 마지막 1번째가 리턴된다는 것? 이 정도만 보시면 됩니다.

 

 

 실행 결과는 위와 같습니다.