프날 오토핫키 강좌  v2

⚠ 이 강좌는 오토핫키 v2를 다룹니다

지금 보시는 강좌는 과거 오랜 시간동안 알려진 오토핫키(v1.1)의 차세대 버전인 오토핫키 v2를 다루고 있습니다.
만약 구버전인 '오토핫키 v1.1'의 강좌를 찾으신다면 프날 오토핫키 강좌(https://pnal.kr)를 봐주시면 되지만, 새로 오토핫키를 배우신다면 v2 버전을 배우시는 것을 강력히 추천드립니다.

80. 문자열 찾기 InStr


이번 강부터 문자열 처리를 위한 여러 테크닉을 배워볼 것입니다. 여러분은 앞으로 어떤 긴 문자열이 있을 때, 이 안에서 또다른 문자열을 찾거나, 자르거나, 대치하는 방법을 익힐 것입니다.

Haystack과 Needle

오늘 배울 내용에 앞서, Haystack과 Needle이라는 두 가지 개념을 이해해 보겠습니다.

  • Haystack: 전체 문자열
  • Needle: 전체 문자열에서 검색할 일부 문자열

Haystack은 작업하고자 하는 전체 문자열을 의미하고, Needle은 문자열 처리 작업을 하기 위해 검색할 문자열을 의미합니다. 따라서 Needle은 Haystack의 일부분입니다.

오늘 우리는 Haystack에서 Needle의 위치를 찾는 방법을 배울 것입니다. 즉, 전체 문자열 속에서 원하는 문자열의 위치를 찾아보겠습니다.

Tip: Haystack과 Needle의 유래

우리나라에 "서울에서 김서방 찾기"라는 속담이 있듯이, 외국에도 무언가 범위가 넓어 찾기 어려운 상황을 일컫을 때 "A needle in a haystack(건초더미에서 바늘 찾기)"이라고 말합니다.

즉, 전체 찾을 범위를 '건초더미(Haystack)', 찾을 대상을 '바늘(Needle)'로 취급하여 오토핫키 프로그래밍에서도 사용합니다.

문자열의 위치

문자열이 좌표도 아닌데 어떻게 위치를 표현할까요? 어렵지 않습니다. 오토핫키에서는 글자 하나의 위치가 1이라고 여기기 때문입니다.

Apple에서 p의 위치는 2와 3이 되겠죠. e의 위치는? 5일 것입니다.

InStr

InStr 함수는 전체 문자열(Haystack) 속에 특정 문자열(Needle)을 검색하여 그 위치를 반환해주는 함수입니다. 문자열을 찾지 못하면 0을 반환합니다.

InStr(Haystack, Needle [, CaseSense, StartingPos, Occurrence])
  • Haystack: 전체 문자열
  • Needle: 찾을 문자열
  • CaseSense: 대소문자 구분 여부
  • StartingPos: 검색 시작 위치
  • Occurrence: 몇 번째 일치 항목의 위치를 가져올 것인지

Haystack / Needle

상술하였으므로 설명은 생략합니다.

CaseSense

기본적으로 InStr을 포함한 거의 모든 오토핫키 함수는 문자열을 처리할 때 대소문자를 구분하지 않습니다. Course 문자열에선 OUR가 존재하는 것이죠.

그러나 이 매개변수에 1(true)을 전달해주면 대소문자를 별도로 취급하게 됩니다. Course에는 OUR가 포함되어있지 않는다고 여깁니다.

StartingPos

Haystack에서 검색을 시작할 위치를 지정합니다. 예를 들어서 Set your course by the stars라는 문자열이 Haystack일 경우, StartingPos가 4라면 your course by the stars 안에서만 Needle을 검색합니다.

Occurrence

찾아진 위치가 여러 개일 경우, 몇 번째 문자열의 위치를 가져올지 정해줍니다.

Apple에서 p를 Needle로 삼아서 InStr를 수행했을 때, 찾아진 위치는 2와 3일 것입니다. 기본적으로 이 함수는 첫 번째 p의 위치인 2를 반환하지만, Occurrence 매개변수에 2를 전달했을 경우 두 번째 p의 위치인 3을 반환할 것입니다.

이곳에 음수를 전달할 수도 있는데, '뒤에서 몇 번째 요소를 가져올지'를 정해줍니다. 예를 들어서 -3을 전달해주면 뒤에서 세 번째 요소의 위치를 반환하게 됩니다.

Tip: 문자열 위치에 음수 표시

StartingPos와 같은 문자열의 위치를 적는 매개변수엔 음수가 들어갈 수 있는데, 이 경우 "뒤에서부터 n번째 위치"로 해석됩니다.

예를 들어서 StartingPos가 -5라면 오른쪽에서 다섯 번째 문자열부터 검색을 시작합니다. 단, Occurrence 매개변수가 지정되지 않으면 오른쪽에서 왼쪽으로 검색을 수행하게 되므로 검색 범위는 [오른쪽에서 다섯번째 문자 ~ 가장 왼쪽 문자]가 됩니다.

실습

1. 전체 문자열 중 010의 위치 가져오기

1info := "홍길동: 돈까스와 제육볶음 010-XXXX-XXXX"
2pos := InStr(info, "010")
3MsgBox(pos)
예제 1. 010의 위치 검색 (결과: 16)

사실 CaseSense부터의 선택 매개변수는 잘 쓰지 않습니다. 가장 많이 쓰는 상황이 위와 같이 특정 문자열의 위치만 정확히 찾는 경우입니다.

어렵지 않죠? 참고로 Needle은 단일 문자가 아니라 위의 010과 같이 문자열일 수 있으며, 이 경우 일치하는 문자열의 첫 번째 위치가 반환됩니다. 따라서 결과는 16이 되겠네요.

2. 문자열이 포함되어 있는지 여부에 따라 조건 분기하기

1context := "별을 보고 항로를 정해라. 지나가는 모든 배의 등불 말고."
2if (InStr(context, "항해"))
3    MsgBox("[항해]가 포함되어 있습니다.")
4else
5    MsgBox("[항해]가 포함되어 있지 않습니다.")
예제 2. '항해'의 위치 검색 (결과: [항해]가 포함되어 있지 않습니다.)

오토핫키에서 0과 공백이 아닌 모든 값은 '참' 취급이라고 말씀드렸죠? 따라서 InStr의 결과가 1이든 20이든 상관없이 조건문 내에선 참일 것입니다. 반대로, Needle이 Haystack 안에 없을 때에만 거짓(0) 취급인 것이죠.

따라서 조건문 내에 비교문을 적어 if (InStr(context, "항해") > 0)이라고 쓰지 않고, 아예 빼서 InStr 구문만 적어주었습니다.

질문하러 가기