문자열 “abc”에 부분 문자열 “a”가 있는지 찾는 방법이 있을까요? 이 글에서는 파이썬 부분 문자열 찾기 방법과 검사 방법을 소개하고자 합니다.
in 연산자로 검사하기
단순히, S 안에 pat이라는 패턴이 있는지 검사한다면, in 연산자를 이용하면 됩니다.
pattern in string
pattern이 string 안에 있는가?
예제를 보겠습니다.
먼저, “b” in “abc.bcd” 입니다. string이 “abc.bcd”이고, pattern이 “b”입니다. 이는
- 문자열 “abc.bcd” 안에
- 문자열 “b”가 있는지 검사함을 의미합니다.
있나요? 2번째 위치와, 5번째 위치에서 찾을 수 있으므로 참입니다. 반면에, “abc.bcd” 안에, “ac”는 없습니다. 따라서, 2번째의 경우 False가 뜨게 됩니다.
이렇게 in 연산자는 어떤 문자열에서 부분 문자열 pattern이 있는지 판단할 수 있습니다. “abc” 안에 “bc”가 있는지 여부를 판단하기 위해서 in 연산자 만을 이용해도 됩니다. 그런데, 이 말은 역으로 말하면, 부분 문자열이 나타나는 위치를 알 수 없다는 의미도 됩니다.
단순히, string에서 pattern이라는 부분 문자열을 찾을 수 있는지 여부만 알 수 있다는 의미입니다. 정보를 조금 더 얻으려면 어떻게 해야 할까요?
파이썬 find 함수로 부분 문자열 위치 찾기
파이썬의 find 함수는 파이썬 부분 문자열이 나타나는 최초의 위치를 돌려줍니다.
S에서 sub를
- 찾을 수 있다면, 그 중 가장 작은 인덱스를 돌려줍니다.
- 그렇지 않으면 -1을 돌려줍니다.
- 2번째 인자인 start를 넘겨주면 부분 분자열의 s번째 위치부터 탐색합니다.
이것도 예제를 한 번 보겠습니다.
예제 2번을 보겠습니다. “abc.bcd”에서 “e”는 찾을 수 있나요? 없습니다. 따라서, 이 경우, -1이 출력됩니다. 그런데 “abc.bcd”에서 “b”는 2군데나 있습니다. 2번째 위치와 5번째 위치에 있지요. 이 중, 인덱스가 작은 쪽은 2번째 입니다. 0 base로 하면 1이지요.
따라서, 예제 2번의 출력 결과는 -1, 1이 됩니다. 그런데, 이 find 함수는 찾은 위치 하나만 돌려줍니다. 모든 위치를 얻어 오려면 어떻게 하면 될까요?
예제 3번 프로그램을 봅시다. target_str은 “abc.bcbcd”이고, 패턴은 “bc”입니다. 현재 cur의 값은 0입니다. 5번째 줄의 while True가 중요합니다. 이 안에 있는 로직을 보겠습니다.
- target_str.find(pattern, cur)가 -1 이면 while loop을 빠져 나옵니다.
- 그렇지 않으면
- loc을 ret에 append 하고
- cur에 loc+1을 추가합니다.
이 알고리즘을 천천히 타고 가 봅시다.
먼저 cur가 0이므로, target string의 0번째 위치부터 “bc”가 있는 최초 위치를 탐색하게 됩니다. 1번째 위치에 있습니다. 그러므로
- ret에 1이 추가됩니다.
- cur의 값은 2가 됩니다.
cur 값이 2가 되었다면, 제가 회색으로 칠한 부분에서만 “bc”가 있는지 탐색할 겁니다. 4번째 위치에 제가 원하는 “bc”가 최초로 나타났습니다. 따라서
- ret에 4가 추가됩니다.
- cur의 값은 5가 됩니다.
다음에, cur 값이 5라면, 회색으로 칠한 부분에 “bc”가 있는지 볼 겁니다. 6번째 위치에 “bc”가 최초로 나타났네요? 따라서
- ret에 6이 추가됩니다.
- cur의 값은 7이 됩니다.
다시 회색 부분에서 “bc”를 찾아봅시다. 이번에는 없습니다. 따라서, find는 -1을 리턴하고 while loop를 빠져나오게 됩니다. 이제 결과를 보겠습니다.
1, 4, 6번째 위치에서 패턴이 나왔다는 결과가 출력됩니다.