GNUEmacsManual:12

From 흡혈양파의 번역工房
Jump to: navigation, search
검색과 대체

검색과 대체

다른 편집기와 마찬가지로 Emacs에도 문자열의 발생을 검색하는 명령어들이 있다. Emacs에는 문자열의 발생을 다른 문자열로 대체하는 명령어들도 있다. 뿐만 아니라 동일한 일을 수행하지만 고정된 문자열 대신 패턴을 검색하는 명령어들도 존재한다.


태그 테이블의 제어 하에 (306 페이지의 25.3.6절 [태그 검색] 참고) 또는 Dired
A
명령어를 통해 (320 페이지의 27.7절 [파일에 작업하기] 참고) 또는
grep
프로그램에 요청을 통해 (264 페이지의 24.4절 [Grep 검색] 참고) 다중 파일을 검색할 수도 있다.


증분 검색

Emacs에서 우선적인 검색 명령어는 증분적으로 이루어지므로 사용자가 검색 문자열의 첫 번째 문자를 입력하는 즉시 검색이 시작된다. 검색 문자열에 입력하는 동안 Emacs는 문자열이 발견될 (지금까지 입력한 내용에 따라) 위치를 보여준다. 그리고 원하는 장소를 확인할 수 있을 만큼 문자를 입력하면 중단해도 좋다. 다음으로 수행할 계획에 따라 RET 을 이용해 검색을 직접 종료하거나 종료하지 않을 수 있다.


C-s 순방향으로 증분 검색한다(
isearch-forward
).


C-r 역방향으로 증분 검색한다(
isearch-backward
).


증분 검색의 기본

C-s 증분 검색을 시작한다(
isearch-forward
).


C-r 역 증분 검색을 시작한다(
isearch-backward
).


C-s (
isearch-forward
)는 순방향 증분 검색을 시작한다. 이는 키보드로부터 문자를 읽어오고, 버퍼에서 그러한 문자열의 다음 발생 끝을 바로 지나서 포인트를 이동시킨다.


예를 들어 C-s 다음에 F 를 입력하면 시작점 이후에 버퍼에서 처음으로 발생하는 '
F
' 이후에 커서를 놓는다. 그리고 사용자가
O
을 입력하면 커서는 첫 번째 '
FO
' 직후로 이동하는데, '
FO
'에서 '
F
'는 이전에 처음으로 발견된 '
F
'가 아닐 수도 있다. 또 다른
O
를 지나 커서는 처음 발견된 '
FOO
' 바로 뒤로 이동한다.


각 단계에서 Emacs 는
isearch
face를 이용해 현재 일치 결과를 강조하는데, 이는 검색 문자열에 일치하는 버퍼 텍스트이다(74 페이지의 11.8절 [Faces] 참고). 현재 검색 문자열도 에코 영역에 표시된다.


검색 문자열을 입력하면서 실수를 범하면 DEL 을 입력한다. DEL 을 입력할 때마다 검색 문자열의 마지막 문자가 취소된다.


도달한 위치가 만족스럽다면 RET 을 입력한다. 그러면 검색이 중지되고 검색으로 커서를 가져온 자리에 커서를 그대로 남겨 둔다. 또한 검색에서 특별한 의미가 없는 명령어는 모두 검색을 중지시킨 후에 실행된다. 따라서 C-a 를 입력하면 검색을 종료한 후 행의 시작으로 이동한다. RET 은 사용자가 입력하고자 하는 다음 명령어가 출력(printing) 문자, DEL, RET, 또는 검색 내에서 특별한 문자(C-q, C-w, C-r, C-s, C-y, M-y, M-r, M-c, M-e 와 아래 설명한 몇 가지도 포함)일 때에만 필요하다.


한 가지 특별한 예외로, 검색 문자열이 비어 있을 때 RET 을 입력하면 비증분 검색을 시작한다(95 페이지의 12.2절 [비증분 검색] 참고).


증분 검색을 종료하면 마크를 활성화하지 않고 포인트의 원래 값을 마크 링으로 추가하므로 C-u C-SPC 를 이용해 검색을 시작하기 전의 위치로 돌아갈 수 있다. 48 페이지의 8.4절 [마크 링]을 참고한다. 이는 마크가 이미 활성화되어 있지 않을 때에만 실행된다.


역방향으로 검색하기 위해서는 C-s 대신 C-r (
isearch-backward
)를 이용해 검색을 시작한다. 역방향 검색(backward search)은 순방향 검색이 시작점 이후에 일치 결과를 찾듯이 시작점 이전에 끝나는 일치 결과를 찾는다.


증분 검색 반복하기

순방향으로 '
FOO
'를 검색하다가 일치 결과를 찾았지만 사용자가 예상한 결과가 아니라 버퍼 뒤에서 발생하는 '
FOO
'를 찾길 원한다고 가정해보자. 이런 경우 검색 문자열의 다음 발생으로 이동하도록 C-s 를 다시 입력한다. 원하는 횟수만큼 반복이 가능하다. 너무 많이 간 경우 DEL 을 이용해 C-s 문자를 몇 개 취소할 수 있다. 이와 마찬가지로 역방향 증분 검색에서는 C-r 을 이용할 때마다 역방향 검색을 반복한다.


증분 검색 중에 잠시 쉬게 되면 Emacs는 화면에 나타나는 검색 문자열에 가능한 일치 결과를 모두 강조한다. 이는 검색을 반복하기 위해 C-s 또는 C-r 을 입력함으로써 도달할 수 있는 위치를 예상하도록 도와준다. 다른 일치 결과들은
lazy-highlight
라는 맞춤 가능한 face를 이용해 현재 일치 결과와 다르게 강조된다(74 페이지의 11.8절 [Faces] 참고). 이 기능이 마음에 들지 않으면
isearch-lazy-highlight
nil
로 설정하여 비활성화시키면 된다.


검색을 종료한 후에 C-s C-s 를 입력하면 동일한 문자열을 다시 검색할 수 있다. 첫 번째 C-s 는 증분 검색을 호출하는 키이고, 두 번째 C-s 는 "다시 검색하라"는 의미다. 이와 마찬가지로 C-r C-r 은 마지막 검색 문자열을 뒤로 검색한다. 마지막 검색 문자열을 결정할 때는 C-sC-r 중 무엇을 이용해 문자열을 검색하였는지는 중요하지 않다.


순방향 검색을 실행하고 있는데 찾는 대상이 시작점 앞에 있음을 인식한 경우 C-r 을 입력하여 검색 문자열은 변경하지 않은 채 역방향 검색으로 전환할 수 있다. 마찬가지로 역방향 검색에서 C-s 를 사용하면 순방향 검색으로 전환된다.


검색이 실패하고 또 C-s 를 입력하여 반복을 요청하는 경우 버퍼의 시작에서 다시 시작된다. C-r 을 이용해 역 검색 실패가 반복될 경우 끝에서부터 다시 시작된다. 이를 wrapping around 라고 부르는데, 발생하고 나면 검색 프롬프트에 '
Wrapped
'라고 나타난다. 검색의 원래 시작점을 넘어 계속하면 '
Overwrapped
' 로 변경되는데, 이는 이미 사용자가 확인한 일치 결과를 다시 방문하고 있음을 의미한다.


이전 검색 문자열을 거부하기 위해서는 검색 문자열을 사용한다. M-pM-n 은 재사용할 검색 문자열을 고르기 위해 링을 거쳐 움직인다. 이러한 명령어들은 선택된 문자열 링 요소를 사용자가 편집할 수 있는 미니버퍼에 남겨 둔다.


미니버퍼에 현재 검색 문자열을 검색 링의 항목으로 대체하지 않고 편집하려면 M-e 를 입력한다. RET, C-s 또는 C-r 을 입력하여 문자열 편집과 검색을 끝마친다.


증분 검색의 오류

문자열이 전혀 발견되지 않으면 에코 영역은 '
Failing I-Search
'라고 말하고, 커서는 Emacs가 사용자의 문자열을 최대한 많이 발견한 장소를 거쳐 이동한다. 따라서 사용자가 '
FOOT
'을 검색하는데 '
FOOT
'이 존재하지 않는다면 '
FOOL
'의 '
FOO
' 다음에 커서를 발견할 것이다. 에코 영역에서 일치에 실패한 검색 문자열의 부분은
isearch-fail
face 를 이용해 강조된다.


이 시점에서 사용자가 할 수 있는 일이 몇 가지 있다. 문자열을 잘못 입력했다면 DEL 을 이용해 일부를 지우고 수정할 수 있다. 하지만 발견한 위치가 마음에 든다면 RET를 입력하여 그 곳에 둔다. 아니면 C-g 를 입력하여 발견할 수 없었던 문자를 검색 문자열로부터 제거하고 ('
FOOT
'의 '
T
') 발견된 것만 남겨둔다('
FOOT
'에서 '
FOO
'). 이 때 C-g 를 두 번째로 사용하면 검색을 전부 취소하고 포인트를 검색이 시작될 때의 위치로 돌려놓는다.


중단 명령어 C-g 는 검색 중에 특별한 일을 실행하는데, 그것이 수행하는 일은 검색 상태에 따라 좌우된다. 검색에서 당신이 명시한 내용을 발견하고 입력을 기다리고 있다면 C-g 는 전체 검색을 취소하고 사용자가 검색을 시작한 곳으로 커서를 이동시킨다. 검색 문자열에 발견되지 않은 문자가 존재할 때 C-g 를 입력하면 Emacs는 여전히 그러한 문자를 검색하거나 검색이 실패할 것이기 때문에 찾지 못한 검색 문자열의 문자는 검색 문자열로부터 파기된다. 문자가 사라지고 나면 검색은 성공적으로 끝나고 추가 입력을 기다리므로 두 번째로 C-g 를 입력해야 전체 검색이 취소될 것이다.


증분 검색을 위한 특수 입력

증분 검색 시 사용자가 입력한 문자 중 일부는 특별한 효과를 가진다.


기본적으로 증분 검색은 lax space matching 을 실행하는데, 이는 텍스트에 하나 또는 그 이상의 공백 시퀀스에 일치하는 공백 또는 공백 시퀀스를 의미한다. 따라서 '
foo bar
'는 '
foo bar
', '
foo bar
', '
foo bar
' 식으로(단, '
foobar
'는 해당하지 않음) 일치 결과를 보인다. 좀 더 정확히 말해 Emacs는 검색 문자열에서 각 공백 문자 시퀀스를
search-whitespace-regexp
변수가 명시한 정규 표현식에 일치시킨다. 가령 공백을 새 행의 시퀀스와 공백에 일치시키기 위해서는 '
"[[:space:]\n] + "
'로 설정한다.


lax space matching 을 토글하려면 M-s SPC (
isearch-toggle-lax-whitespace
)을 입력한다. 또 이 기능을 완전히 끄기 위해
search-whitespace-regexp
nil
로 변경하면, 검색 문자열의 공백이 정확히 하나의 공백에 일치할 것이다.


사용자가 입력한 검색 문자열에 소문자로 된 글자만 포함하면 검색은 대, 소문자를 가리지 않고, 대문자로 된 글자가 검색 문자열에 존재해야만 검색이 대, 소문자에 민감해진다. 검색 문자열에서 대문자로 된 문자를 삭제하면 이 효과는 사라진다. 102 페이지의 12.9절 [검색 대, 소문자]를 참고한다.


보이지 않는 텍스트의 검색 여부를 토글하려면 M-s i (
isearch-toggle-invisible
)을 입력한다. 이와 관련 내용은 220 페이지의 [개요 검색]을 참고한다.


새 행 문자를 검색하려면 C-j 를 입력한다.


Non-ASCII 문자를 검색하려면 다음 방법 중 하나를 사용한다:

  • C-q 다음에 비그래픽(non-graphic) 문자나 8진수 시퀀스를 입력한다. 이는 문자를 검색 문자열로 추가하며, C-q 를 이용해 버퍼로 삽입하는 것과 비슷하다(16 페이지의 4.1절 [텍스트 삽입하기] 참고). 예를 들어 증분 검색 중에 C-q C-s 는 '
    control-S
    ' 문자를 검색 문자열로 추가한다.
  • C-x 8 RET 다음에 Unicode 이름 또는 code-point를 입력한다. 이는 명시된 문자를 검색 문자열로 추가하는데, 일반적인
    insert-char
    명령어와 비슷하다(16 페이지의 4.1절 [텍스트 삽입하기] 참고).
  • 입력 방법을 사용한다(181 페이지의 19.3절 [입력 방법] 참고). 검색을 시작할 때 현재 버퍼에서 입력 방법이 활성화되면 검색 문자열에서도 사용할 수 있다. 검색 문자열을 입력하는 동안 C-\ (
    isearch-toggle-input-method
    )를 이용해 입력 방법을 토글할 수 있다. C-^ (
    isearch-toggle-specified-input-method
    )를 이용하면 기본값이 아닌 입력 방법을 켤 수도 있는데, 입력 방법 이름을 요구할 것이다. 증분 검색 중에 입력 방법이 활성화되면 검색 프롬프트는 다음과 같이 입력 방법 연상 기호를 포함할 것이다:
    I-search [im]:
    
    여기서 im 은 활성 입력 방법의 연상 기호다. 증분 검색 중에 활성화한 입력 방법이 무엇이든 이후에 현재 버퍼에 활성화된 채로 남는다.


증분 검색에서 M-% 를 입력하면 현재 검색 문자열을 대체할 문자열로 사용하여
query-replace
또는
query-replace-regexp
(검색 모드에 따라)를 호출한다. 음수로 된 접두 인자는 역방향으로 대체함을 의미한다. 105 페이지의 12.10.4절 [쿼리 대체]를 참고한다.


증분 검색에서 M-TAB 을 입력하면
isearch-complete
를 호출하는데, 이는 검색 문자열을 완성 대안 목록으로 사용하여 검색 문자열의 완성을 시도한다. 28 페이지의 5.4절 [완성]을 참고한다. 많은 운영체제에서 M-TAB 키 시퀀스는 창 관리자에 의해 포착되므로 사용을 원한다면 사용자는
isearch-complete
를 다른 키 시퀀스로 재바인딩해야 한다(431 페이지의 33.3.5절 [재바인딩] 참고).


증분 검색이 활성화되면 C-h C-h 를 입력하여 특수 키 바인딩 목록을 포함해 대화형 도움말 옵션으로 접근 가능하다. 이러한 키 바인딩은 키맵
isearch-mode-map
의 일부이다(429 페이지의 33.3.1절 [키맵] 참고).


Isearch 붙이기

증분 검색에서 C-y (
isearch-yank-kill
)는 검색 문자열 뒤에 현재 제거 내용(kill)을 붙인다. C-y 이후에 M-y (
isearch-yank-pop
)를 호출하면 일반 M-y (
yank-pop
) 명령어와 비슷하게 뒤로 추가된(appended) 텍스트를 이전 제거 내용으로 대체한다(55 페이지의 9.2절 [붙여넣기] 참고). Mouse-2 는 현재 X 선택 영역을 덧붙인다(58 페이지의 9.3.2절 [일차 선택] 참고).


C-w (
isearch-yank-word-or-char
)는 포인트에서 다음 문자 또는 단어를 검색 문자열 뒤에 덧붙인다. 이는 포인트에 텍스트의 또 다른 발생을 쉽게 검색하는 방법이다. (문자나 단어의 복사 유무는 개인에 따라 결정된다.)


마찬가지로 M-s C-e (
isearch-yank-line
)는 검색 문자열 뒤에 현재 행의 나머지 부분을 추가한다. 포인트가 이미 행 끝에 위치한 경우 다음 행의 뒤에 추가한다. 수치적 인자 n 을 이용해 다음 n 개 행 뒤에 붙일 수 있다.


검색이 현재 대, 소문자에 민감하지 않은 경우 C-wM-s C-e 모두 복사하는 텍스트를 소문자로 변환하여 검색이 대, 소문자에 민감하지 않은 채로 남는다.


C-M-w (
isearch-del-char
)는 검색 문자열로부터 마지막 문자를 삭제하고, C-M-y (
isearch-yank-char
)는 포인트 이후의 문자를 검색 문자열 뒤에 덧붙인다. 포인트 이후 문자를 추가하는 대안 방법으로 M-e 를 이용해 미니버퍼로 들어가 (91 페이지의 12.1.2절 [증분 검색 반복하기] 참고) 미니버퍼의 검색 문자열 끝에서 C-f 를 입력하는 방법이 있다.


증분 검색 종료하지 않기

여기서는 증분 검색에 해당하는 내용이 아니긴 하지만, 진행 중인 증분 검색을 종료하지 않고 사용자가 입력하는 두 범주의 명령어를 설명하고자 한다.


접두 인자
증분 검색에서 사용자가 접두 인자를 입력하면 (23 페이지의 4.10절 [인자] 참고) 기본적으로 검색 내 다음 액션 또는 검색을 종료하는 명령어에 적용된다. Emacs 이전 버전에서는 접두 인자를 입력하면 항상 검색을 중단시켰다.
isearch-allow-prefix
nil
로 설정하면 그러한 행위로 되돌릴 수 있다.
isearch-allow-scroll
nil
이 아니면 (아래 참고) 접두 인자는 항상 위에 설명된 기본 행위를 가질 것이다.


스크롤 명령어
보통 스크롤 명령어는 증분 검색을 종료한다.
isearch-allow-scroll
변수를
nil
이 아닌 값으로 변경하면 C-v, M-v, C-l 과 같은 키보드 스크롤 명령어를 비롯해 스크롤 바의 사용을 활성화한다(69 페이지의 11.1절 [스크롤] 참고). 이는 키 시퀀스에 대한 바인딩을 통해 이러한 명령어를 호출하는 경우만 해당하는데, M-x 를 입력하면 검색은 여전히 종료될 것이다. 일반적인 방식으로 이러한 명령어에 접두 인자를 제공하면 된다. 단, 이 기능을 사용하면 현재 일치 결과를 시야 밖으로 스크롤하지 못한다.
isearch-allow-scroll
기능은 C-x 2 (
split-window-below
)와 C-x ^ (
enlarge-window
)처럼 사실상 스크롤되진 않지만 텍스트가 화면에 나타나는 위치에 영향을 미치는 몇 가지 다른 명령어에도 영향을 미친다.
nil
값이 아닌
isearch-scroll
속성을 이름으로 가진 명령어에는 모두 적용된다. 따라서 사용자는 이러한 속성을 변경하여 어떤 명령어가 영향을 받는지 제어할 수 있다.
예를 들어 향후 Emacs 세션에서 증분 검색에 C-h l 을 사용 가능하게 만들고 싶다면 C-h c 를 이용해 그것이 실행하는 명령어가 무엇인지, 즉
view-lossage
임을 알아낸다(39 페이지의 7.1절 [키 도움말] 참고). 그리고 나서 아래의 행을 init 파일로 넣을 수 있다(437 페이지의 33.4절 [Init 파일] 참고):
(put 'view-lossage 'isearch-scroll t)
해당 기능은 포인트, 버퍼 내용, 매치 데이터, 현재 버퍼, 또는 선택된 창과 프레임을 영구적으로 변경하지 않는 명령어에는 모두 적용 가능하다. 명령어 자체가 증분 검색을 시도해선 안 된다.


미니버퍼 검색하기

미니버퍼가 활성화되어 있을 때 증분 검색을 시작하면 Emacs는 미니버퍼의 내용을 검색한다. 일반 버퍼의 검색과 달리 검색 문자열이 에코 영역에 표시되지 않는데, 미니버퍼를 표시하는 데에 사용되기 때문이다.


증분 검색이 미니버퍼에서 실패하면 미니버퍼 히스토리의 검색을 시도한다. 32 페이지의 5.5절 [미니버퍼 히스토리]를 참고한다. 미니버퍼와 그 히스토리를 일련의 "페이지"로 시각화하여 가장 오래된 히스토리 요소를 첫 페이지에 두고 가장 최근의 미니버퍼는 마지막 페이지에 둔다. 순방향 검색 C-s 는 뒷페이지까지 순방향으로 검색을 진행하고, 역방향 검색 C-r 은 앞페이지까지 역방향으로 검색한다. 일반 버퍼 검색과 마찬가지로 검색 실패는 마지막 페이지에서 첫 페이지로, 첫 페이지에서 마지막 페이지로 래핑(wrap around)을 야기할 수 있다.


버퍼 일치 결과가 히스토리 요소에 있을 경우 해당 히스토리 요소가 미니버퍼로 들어오게 된다. 사용자가 증분 검색을 정상적으로 종료하면 (예: RET 을 입력하여) 후에 미니버퍼에 남아 있는다. C-g 를 이용해 검색을 취소하면 사용자가 검색을 시작할 때 미니버퍼의 내용을 복구한다.


비증분 검색

Emacs는 비증분 검색 명령어도 제공하는데, 이는 검색이 시작되기 전에 사용자가 전체 검색 문자열을 입력하도록 요구한다.


C-s RET string RET string을 검색한다.


C-r RET string RET string을 역방향으로 검색한다.


비증분 검색을 시작하려면 먼저 C-s RET 을 입력한다. 그러면 미니버퍼로 들어가 검색 문자열을 읽는데, RET 을 이용해 문자열을 종료하면 검색이 진행된다. 문자열이 발견되지 않으면 검색 명령어는 오류를 보낸다.


C-s RET 을 입력할 때 C-s 는 평소처럼 증분 검색을 호출한다. 이 명령어는 사용자가 명시한 문자열이 비어 있을 경우 비증분 검색을 위한 명령어
search-forward
를 호출하도록 특별히 프로그램화되었다. (그렇지 않으면 빈 인자는 무용지물일 것이다.) C-r RET 도 마찬가지로
search-backward
명령어를 호출한다.


단어 검색

단어 검색은 단어의 시퀀스 사이에 구두점 유형과 상관없이 단어 시퀀스를 검색한다. 예를 들어 사용자가 하나의 공백으로 구분된 두 단어로 구성된 검색 문자열을 입력하면 검색은 하나 또는 그 이상의 공백, 새 행 혹은 기타 구두점 문자로 구분된 해당 두 단어의 어떤 시퀀스에도 일치시킬 것이다. 이는 찾고자 하는 단어가 새 행이나 공백으로 구분되어 있는지 걱정할 필요가 없기 때문에 텍스트 문서를 검색 시 유용하다.


M-s w 증분 검색이 활성화되어 있다면 단어 검색 모드를 토글하고 (
isearch-toggle-word
) 그렇지 않으면 순방향 증분 검색을 시작한다 (
isearch-forward-word
).


M-s w RET words RET 순방향 비증분 단어 검색을 이용해 words를 검색한다.


M-s w C-r RET words RET 비증분 단어 검색을 이용해 words를 역방향으로 검색한다.


순방향 증분 단어 검색을 시작하려면 M-s w 를 입력한다. 증분 검색이 이미 활성화되어 있지 않다면 이는
isearch-forward-word
명령어를 실행할 것이다. 증분 검색이 이미 활성화되어 있다면 (순방향 검색이든 역방향 검색이든) M-s w 는 검색 방향은 유지한 채 단어 검색으로 전환하여 현재 검색 문자열은 변경되지 않는다. M-s w 를 다시 입력하면 단어 검색을 토글하여 다시 끌 수 있다.


비증분 단어 검색을 시작하려면 순방향 검색은 M-s w RET 을, 역방향 검색은 M-s w C-r RET 을 입력한다. 이는 각각
word-search-forward
word-search-backward
를 실행할 것이다.


증분 및 비증분 단어 검색은 일치 결과를 찾는 방식에 있어 약간 차이를 보인다. 비증분 단어 검색에서는 검색 문자열의 각 단어가 정확히 전체 단어에 일치해야 한다. 비증분 단어 검색에서는 매칭이 조금 느슨하여 사용자가 검색 문자열을 입력 시 첫 단어와 마지막 단어는 전체 단어에 일치할 필요가 없다. 이는 사용자가 입력하는 동안 증분적으로 매칭이 진행될 수 있도록 하기 위함이다. 전체 단어와 모두 일치해야 하는 느린 강조(lazy highlight)에서는 이러한 유연성이(laxity) 적용되지 않는다.


심볼 검색

심볼 검색(symbol search)은 검색의 경계가 심볼 경계에 일치해야 한다는 점만 제외하면 일반 검색과 많이 닮았다. 이러한 맥락에서 심볼의 의미는 주 모드에 따라 좌우되고, 주로 Emacs Lisp 모드에서 Lisp 심볼처럼 소스 코드 토큰(token)을 참조한다. 예를 들어 Lisp 심볼 forward-word 에 대한 증분 심볼 검색을 실행하면
isearch-forward-word
에는 일치하지 않을 것이다. 따라서 이 기능은 소스 코드를 검색 시 주로 유용하게 사용된다.


M-s _ 증분 검색이 활성화되면 심볼 검색 모드를 토글하고 (
isearch-toggle-symbol
) 그렇지 않으면 순방향 증분 심볼 검색을 시작한다(
isearch-forward-symbol
).


M-s . 처음에 검색 문자열에 추가된 포인트 근처에서 심볼을 이용해 심볼 증분 검색을 순방향으로 시작한다.


M-s _ RET symbol RET 비증분적으로 symbol에 대한 순방향 검색을 실행한다.


M-s _ C-r RET symbol RET 비증분적으로 symbol에 대한 역방향 검색을 실행한다.


순방향 증분 심볼 검색을 시작하려면 M-s _ (검색할 심볼이 포인트 부근에 있을 때는 M-s . 를 입력)를 입력한다. 증분 검색이 이미 활성화되어 있지 않으면 이는 isearch-forward-symbol 명령어를 실행시킨다. 증분 검색이 이미 활성화되어 있다면 M-s_ 는 심볼 검색으로 전환되어 검색 방향과 현재 검색 문자열을 유지하는데, M-s_ 를 다시 입력하면 심볼 검색을 비활성화시킨다. 증분 심볼 검색에서는 검색 문자열의 시작만 심볼의 시작에 일치하도록 요구한다.


비증분 심볼 검색을 시작하려면 순방향 검색에는 M-s_ RET 을, 역방향 검색에는 M-s_ C-r RET 을 입력한다. 비증분 심볼 검색에서 검색 문자열의 시작과 끝은 각각 심볼의 시작과 끝에 일치해야 한다.


정규 표현식 검색

정규 표현식(또는 줄여서 regexp)은 일치시킬 대안 문자열의 클래스를 나타내는 패턴이다. Emacs는 regexp에 대한 일치 결과를 검색하기 위해 증분적 방식과 비증분적 방식을 모두 제공한다. 정규 표현식의 구문은 다음 절에서 설명하겠다.


C-M-s 증분 regexp 검색을 시작한다(
isearch-forward-regexp
).


C-M-r 역(reverse)증분 regexp 검색을 시작한다(
isearch-backward-regexp
).


regexp 에 대한 증분 검색은 C-M-s (
isearch-forward-regexp
)를 입력하거나, 수치적 인자를 (값이 중요하지 않은) 이용해 C-s 를 입력하거나, 순방향 증분 검색 내에서 M-r 를 입력하여 이루어진다. 이 명령어는 C-s 와 같이 검색 문자열을 증분식으로 읽지만 버퍼에서 텍스트에 정확히 일치하는 결과를 찾기보다는 검색 문자열을 regexp 로 취급한다. 사용자가 검색 문자열로 텍스트를 추가할 때마다 regexp 는 더 길어지고 새로운 regexp 가 검색된다. regexp를 거꾸로 검색하려면 C-M-r (
isearch-backward-regexp
), 접두 인자가 있는 C-r, 또는 역방향 증분 검색에서 M-r 을 사용한다.


일반 증분 검색에서 모든 특수 키 시퀀스는 증분 regexp 검색에서도 비슷한 행동을 취한다. 가령 검색을 시작한 직후에 C-s 를 입력하면 사용된 마지막 증분 검색 regexp를 복구시키고 그것을 순방향으로 검색한다. regexp 및 non-regexp 증분 검색은 서로 다른 기본값을 가진다. 또한 구분된 검색 링을 가지므로 사용자는 M-pM-n 을 이용해 접근할 수 있다.


일반 증분 검색과 달리 증분 regexp 검색은 기본적으로 lax space matching 을 사용하지 않는다. 이 기능을 토글하려면 M-s SPC (
isearch-toggle-lax-whitespace
)를 사용한다. 그리고 나서 증분 regexp 검색에 SPC 를 입력하면 하나 또는 이상의 여백 문자로 된 시퀀스에 일치시킬 것이다.
search-whitespace-regexp
변수는 lax space matching 에 대한 regexp를 명시한다. 92 페이지의 12.1.4절 [특수 Isearch]를 참고한다.


일부 사례의 경우 증분 regexp 검색에서 regexp 에 문자를 추가하면 커서를 이동시켜 와서 다시 시작할 수 있다. 예를 들어 '
foo
'를 검색하고 '
\|bar
' 를 추가하였다면 첫 번째 '
bar
'가 첫 번째 '
foo
'를 앞설 경우를 대비해 커서가 백업된다. 97 페이지의 12.6절 [Regexps]를 참고한다.


순방향 및 역방향 regexp 검색은 대칭적으로 이루어지지 않는 것이, Emacs에서 regexp의 매칭은 항상 regexp의 시작 부분부터 시작해 순방향으로 작동하기 때문이다. 따라서 순방향 regexp 검색은 순방향으로 스캔하고, 가능한 시작점 위치마다 순방향 일치를 시도한다. 역방향 regexp 검색은 역방향으로 스캔하고, 가능한 시작점 위치마다 순방향 일치를 시도한다. 이러한 검색 방법들은 mirror image 가 아니다.


regexp 에 대한 비증분 검색은
re-search-forward
re-search-backward
명령어로 이루어진다. 이러한 명령어들은 M-x 를 이용하거나 C-M-s RETC-M-r RET 을 이용한 증분 regexp 검색을 통해 호출할 수 있다.


접두 인자를 이용해 증분 regexp 검색 명령어를 사용할 경우
isearch-forward
isearch-backward
처럼 일반 문자열 검색을 실행한다. 90 페이지의 12.1절 [증분 검색]을 참고한다.


정규 표현식의 구문

이번 매뉴얼은 사용자가 주로 사용하는 정규 표현식 기능을 설명한다. Lisp 프로그램에서 주로 사용되는 추가 기능은 The Emacs Lisp Reference Manual 의 "Regular Expressions" 절을 참고한다.


정규 표현식은 특수 구조체인 문자 몇 개와 나머지는 일반으로 구성된 구문을 갖는다. 일반 문자는 동일한 문자에만 일치시키고 나머지는 일치시키지 않는다. 특수 문자는 '
$^.*+?[\
'이다. '
]
' 문자는 문자 대안을 끝마칠 경우 특수로 간주한다(나중에 소개하겠다). '
-
' 문자는 문자 대안에서 특수 문자가 된다. 정규 표현식에 나타나는 그 외 다른 문자는 앞에 '
\
'가 붙지 않는 이상 일반문자다. (Lisp 프로그램에서 정규 표현식을 사용할 때는 모든 '
\
'가 이중으로 사용되어야 하는데, 이번 절 마지막 부분에 사용된 예를 참고한다.)


예를 들어 '
f
'는 특수 문자가 아니고 일반 문자이므로 '
f
' 는 '
f
' 문자열에 일치하고 나머지 문자열은 어떤 것도 일치하지 않는 정규 표현식이다. ('
ff
' 문자열에는 일치시키지 않는다.) 마찬가지로 '
o
'는 '
o
'에만 일치시키는 정규 표현식이다. (대, 소문자 구별이 무시되면 이러한 regexps는 '
F
'와 '
O
'에도 일치시키겠지만 그럴 경우 예외라기보다는 "동일한 문자열"의 일반화로 간주한다.)


두 개의 정규 표현식 ab 는 합치기가 가능하다. 그 결과 a 가 어떤 문자열의 시작 부분 일부와 일치하고 b 가 그 나머지 문자열에 일치하면 전체 문자열에 일치하는 정규 표현식이 생긴다. 예를 들어, 정규 표현식 '
f
'와 '
o
'를 합하면 정규 표현식 '
fo
'가 제공되고, 이는 '
fo
' 문자열에만 일치시킨다. 아직은 특별한 게 없다. 좀 더 특별하게 사용하려면 특수 문자 중 하나를 이용해야 한다. 몇 가지를 열거하겠다.


.
(마침표-period)는 새 행을 제외한 어떤 단일 문자에든 일치시키는 특수 문자이다. 예를 들어 정규 표현식 '
a.b
'는 '
a
'로 시작해 '
b
'로 끝나는 3개 문자 문자열은 무엇이든 일치시킨다.


*
자체는 구조체가 아니며, 원하는 수만큼 가능한 많은 선행(preceding) 정규 표현식을 일치시킴을 의미하는 후위(postfix) 연산자이다. 따라서 '
o
'는 '
o
'가 없는 경우도 포함해 몇 개의 'o'든 일치시킨다.
'
*
'는 항상 최소한으로 가능한 선행 표현식에 적용된다. 따라서 '
fo*
'는 반복되는 '
fo
'가 아니라 반복되는 '
o
'를 갖는다. 이는 '
f
', '
fo
', '
foo
' 등에 일치시킨다.
matcher 는 발견할 수 있는 반복을 즉시 가능한 한 많이 일치시킴으로써 '
*
' 구조체를 처리한다. 그리고 패턴 나머지를 계속한다. 이것이 실패하면 역추적이 발생하여 '
*
'가 수정된('
*
'-modified) 구조체의 일치 결과 중 일부가 나머지 패턴에 일치시킬 수 있게 되면 그러한 일치 결과를 버린다. 예를 들어 '
ca*ar
'를 '
caaar
' 문자열에 일치시킬 때 '
a*
'는 먼저 세 개의 '
a
'에 일치를 시도하지만 패턴 나머지는 '
ar
'이고 일치시킬 것은 '
r
'만 남았으므로 이 시도는 실패한다. 다음 대안은 '
a*
'가 두 개의 '
a
'에만 일치시키는 경우다. 이것을 선택하면 regexp 의 나머지는 성공적으로 매칭이 이루어진다.


+
는 선행 표현식을 적어도 한 번은 일치시켜야 한다는 점은 제외하면 '
*
'와 비슷한 후위 연산자이다. 따라서 '
ca+r
' 은 '
car
' 문자열과 '
caaaar
' 문자열에 일치시키지만 '
cr
' 문자열에는 일치시키지 않는 반면 '
ca*r
'는 세 가지 문자열 모두 일치시킨다.


?
는 선행 표현식을 한 번 또는 전혀 일치시키지 않는다는 점은 제외하면 '
*
'와 비슷한 후위 연산자이다. 따라서 '
ca?r
'은 '
car
' 또는 '
cr
'를 제외한 어떤 것에도 일치시키지 않는다.


*?, +?, ??
는 위 연산자들의 최소 (non-greedy) 변형체다. 일반 연산자 '
*
', '
+
', '
?
'는 전체적인 regexp가 일치시킬 수 있는 한 가능한 많이 일치시킨다. 잇따라 '
?
'를 사용하면 최소한으로 일치시킬 것이다.
따라서 '
ab*
'와 '
ab*?
' 둘 다 '
a
' 문자열과 '
abbbb
' 문자열에 일치할 수 있지만 둘 다 '
abbb
' 텍스트에 일치시키려 하면 '
ab*
'는 전부 (가장 긴 유효 일치 결과) 일치시키는 반면 '
ab*?
'는 '
a
'에만 (가장 짧은 유효 일치 결과) 일치시킨다.
최소 연산자는 주어진 시작점에서 시작해 가능한 한 최소 길이의 문자열에 일치시키고, 순방향 검색에서는 일치 결과에 대해 항상 가장 빠른 시작점이 선택된다. 따라서 '
abbab
' 텍스트 다음에 새 행이 있을 때 '
a.*?$
'를 검색하면 전체 문자열이 일치된다. 처음으로 만나는 '
a
' 부터 일치를 시작할 수 있으므로 그렇게 수행한다.


\{n\}
n 회 반복을 명시하는 후위 연산자로, 앞선 정규 표현식이 행에서 정확히 n 번 일치해야 함을 명시한다. 예로 '
x\{4\}
'는 '
xxxx
' 문자열에만 일치시킨다.


\{n,m\}
nm 사이의 반복을 명시하는 후위 연산자로, 선행 정규 표현식은 적어도 n 회 일치하되 m 회를 초과해선 안 된다. m 이 누락되면 상한 한계가 없어지지만 선행 정규 표현식은 최소 n 회만큼은 일치시켜야 한다.
'
\{0,1\}
'은 '
?
'와 동일하다.
'
\{0,\}
'은 '
*
'와 동일하다.
'
\{1,\}
'은 '
+
'와 동일하다.


[ ... ]
는 '
[
'로 시작해 '
]
'로 끝나는 문자 집합이다.
가장 단순한 경우는 이 집합이 일치할 수 있는 문자가 두 개의 대괄호 안에 위치한 경우다. 따라서 '
[ad]
'는 하나의 '
a
' 또는 하나의 '
d
'에 일치시키고 '
[ad]*
'는 '
a
'들과 '
d
'들로 (빈 문자열도 포함) 구성된 문자열이라면 무엇이든 일치시킨다. 따라서 '
c[ad]*r
' 는 '
cr
', '
car
', '
cdr
', '
caddaar
' 등에 일치시킨다.
문자 집합에는 중간에 '
-
'로 시작하고 끝나는 문자를 써서 문자 범위를 포함시킬 수도 있다. 따라서 '
[a-z]
'는 여느 소문자로 된 ASCII 문자든 모두 일치시킨다. 범위는 소문자로 된 ASCII 문자나 '
$
', '
%
', 또는 마침표라면 무엇이든 일치시키는 '
[a-z$%.]
' 와 같이 각 문자들과 자유롭게 섞어 쓸 수 있다.
문자 집합에는 특정 특수 문자 클래스를 포함시킬 수도 있다. '
[:
'와 균형을 맞추는 '
:]
' 는 문자 대안 안에서 문자 클래스를 감싼다. 가령 '
[[:alnum:]]
'는 어떤 글자나 숫자도 일치시킨다. 문자 클래스의 목록은 The Emacs Lisp Reference Manual 의 "Char Classes" 절을 참고한다.
문자 집합에 '
]
'를 포함시키려면 그것을 첫 번째 문자로 만들어야 한다. 예를 들어 '
[]a]
' 는 '
]
' 또는 '
a
'에 일치시킨다. '
-
'를 포함시키려면 '
-
'를 집합의 첫 번째 문자 또는 마지막 문자로 작성하거나 범위 다음에 놓는다. 따라서 '
[]-]
'는 '
]
'와 '
-
'에 모두 일치시킨다.
'
^
'를 집합에 포함시키려면 집합의 시작을 제외한 어디든 놓아도 좋다. (시작에 놓으면 집합을 보완하는데, 관련 내용은 아래 내용을 참고한다.)
대, 소문자에 민감하지 않은 검색에서 범위를 사용할 때는 범위의 양끝 모두 대문자 또는 양 끝 모두 소문자로 작성해야 하고, 그렇지 않으면 둘 다 글자가 아니어야(non-letter)한다. '
A-z
'처럼 대, 소문자가 섞인 범위의 행위는 바람직하지 못한 정의로, 향후 Emacs 버전에서 변경될 수 있다.


[^...]
'
[^
' 는 보완된 문자 집합을 시작하여 명시된 문자만 제외하고 모든 문자에 일치시킨다. 따라서 '
[^a-z0-9A-Z]
'는 ASCII 글자와 숫자를 제외한 모든 문자에 일치시킨다.
'
^
'는 첫 번째 문자로 사용되지 않는 이상 문자 집합에서 특수 문자가 아니다. '
^
' 다음에 따라오는 문자가 첫 문자로 취급된다(다시 말해 '
-
'와 '
]
'는 특수 문자가 아니란 뜻이다).
새 행을 일치시키지 말아야 할 문자 중 하나로 언급하지 않는 이상 보완된 문자 집합은 새 행을 일치시킬 수 있다. 이는 grep과 같은 프로그램에서 regexps의 처리와 상반된다.


^
는 빈 문자열에 일치시키는 특수 문자지만 일치되는 텍스트에서 행의 시작 부분에서만 일치된다. 그렇지 않으면 어떠한 매칭도 실패한다. 따라서 '
^foo
'는 행의 시작에서 발생하는 '
foo
'에 일치시킨다.
버전들 간 호환성을 위해 '
^
'는 정규 표현식의 시작에서만 혹은 '
\(
' 또는 '
\
' 뒤에서만 이러한 의미로 사용될 수 있다.


$
는 '
^
'와 비슷하지만 행의 끝에서만 일치시킨다. 따라서 '
x+$
'는 행의 끝에서 하나 또는 그 이상의 '
x
'를 가진 문자열에 일치시킨다.
버전들 간 호환성을 위해 '
$
'는 정규 표현식의 끝에서만 혹은 '
\)
' 또는 '
\
' 앞에서만 이러한 의미로 사용될 수 있다.


\
에는 두 가지 기능이 있는데, 우선 특수 문자('
\
' 포함)를 인용하고, 추가 특수 구조체를 소개하는 것이다.
'
\
'는 특수 문자를 인용하므로 '
\$
'는 '
$
'만 일치시키는 정규 표현식이고 '
\[
'는 '
[
'에만 일치시키는 정규 표현식이다.
'
\
'로 시작하는 특수 구조체를 다룬 다음 절을 참고한다.


참고: 기존 버전과 호환성을 위해 특수 문자는 특별한 의미가 통하지 않는 컨텍스트에서는 일반 문자로 취급된다. 예를 들어 '
*foo
' 는 '
*
'가 실행할 선행(preceding) 표현식이 없기 때문에 '
*
'를 일반 문자로 취급한다. 이러한 행위에 의존하는 연습은 바람직하지 못한 행동이므로, 나타나는 장소와 상관없이 특수 문자를 인용하는 것이 바람직하다.


'
\
'는 문자 대안 안에서 특별하지 않으므로 '
-
' 또는 '
]
'의 특수 의미를 절대 제거할 수 없다. 따라서 사용자는 이러한 문자들이 특별한 의미를 지니지 않는다 하더라도 이 문자들에 인용 부호를 붙여선 안 된다. 인용 부호를 붙여도 전혀 명확해지지 않는 이유는 백슬래시를 제외한 모든 단일 문자에 일치시키는 '
["\]
' (Lisp 문자열 구문에는 "
["\\]
")처럼 백슬래시는 특별한 의미를 가지는 위치에서는 이러한 문자들을 선행하여 사용될 수 있기 때문이다.


정규 표현식에서 백슬래시

대부분은 '
\
' 다음에 어떤 문자가 오든 그 문자에만 일치를 시킨다. 하지만 몇 가지 예외가 있는데, '
\
' 로 시작하는 2-문자 시퀀스는 특별한 의미를 지닌다. 시퀀스에서 두 번째 문자를 따로 사용하면 항상 일반 문자가 된다. '
\
' 구조체의 테이블을 아래에 소개하겠다.


\|
대안(alternative)을 명시한다. 두 개의 정규 표현식 ab 사이에 '
\|
'가 있으면 일부 텍스트에 a 가 일치하거나 b 가 일치하는 표현식을 형성한다. a 의 일치를 시도하여 실패하면 b 의 일치를 시도한다. 따라서 'foo\|bar'는 'foo' 또는 'bar'에 일치시키지만 다른 문자열에는 일치시키지 않는다.
\|
는 주변에 가능한 가장 큰 표현식에 적용된다. 주변 '
\(...\)
' 그루핑만
\|
의 grouping power 를 제한할 수 있다.
전체 역추적(backtracking) 기능은 '
\|
' 의 다중 사용을 처리하기 위해 종료된다.


\( ... \)
는 세 가지 목적을 수행하는 그루핑(grouping) 구조체다:
1. 다른 연산에 대한 '
\|
' 대안의 집합을 둘러싼다. 따라서 '
\(foo\|bar\)x
' 는 '
foox
' 또는 '
barx
'에 일치시킨다.
2. 후위 연산자 '
*
', '
+
', '
?
'에 대해 작업할 복잡한 정규식을 둘러싼다. 따라서 '
ba\(na\)*
' 는 '
na
' 문자열을 원하는 수만큼 이용해 (0 또는 그 이상) '
banana
' 등에 일치시킨다.
3. 향후 참조를 위해 일치한 하위문자열을 기록한다.
마지막 적용은 삽입 가능한(parenthetical) 그룹화 개념의 결과가 아니라 동일한 '
\( ... \)
' 구조체에 두 번째 의미로서 할당된 다른 기능이다. 실제로 두 의미에 충돌은 없으며, 충돌이 있을 경우 "shy" 그룹을 이용하면 된다.


\(?: ... \)
는 일치한 하위문자열을 기록하지 않는 "shy" 그룹을 명시하며, '
\d
'를 이용해 그것으로 다시 참조할 수 없다. 이는 정규 표현식들을 기계적으로 결합할 때 유용하므로, 사용자는 참조하도록 된 그룹에 대해 번호 매김을 방해하지 않으면서 구문적 목적으로 그룹을 추가할 수 있다.


\d
는 '
\( ... \)
' 구조체의 d번째 발생에 일치한 것과 동일한 텍스트를 일치시킨다. 이를 역 참조(back reference)라고 부른다.
'
\( ... \)
' 구조체 끝에 matcher는 해당 구조체에서 일치한 텍스트의 시작과 끝을 기억한다. 그리고 후에 정규 표현식에서 '
\
' 다음에 d 숫자를 이용해 '
\( ... \)
' 구조체에 의해 d 번째로 일치한 것과 동일한 텍스트에 일치시킴"을 의미한다..
정규 표현식 처음부터 9개 '
\( ... \)
' 구조체에 일치하는 문자열에는 정규 표현식에서 열린 괄호가 나타나는 순으로 1부터 9까지 숫자가 할당된다. 따라서 '
\1
'부터 '
\9
'까지 이용해 그에 상응하는 '
\( ... \)
' 구조체에 일치한 텍스트를 참조할 수 있다.
예를 들어 '
\(.*\)\1
'는 두 개의 동일한 half로 구성된 newline-free 문자열에 일치한다. '
\(.*\)
'는 무엇이든 가능한 첫 번째 half 일치하는 반면 잇따른 '
\1
'는 정확히 동일한 텍스트에 일치해야 한다. 특정 '
\( ... \)
' 구조체가 한 번 이상 일치하는 경우 (그 뒤에 '
*
'가 따라오면 이런 경우는 쉽게 발생) 마지막 일치 결과만 기록된다.


\'
는 빈 문자열에 일치하지만 일치시키는 버퍼나 문자열의 (또는 그 접근 가능한 부분) 시작에서만 일치시킨다.


\'
는 빈 문자열에 일치하지만 일치시키는 버퍼나 문자열의 (또는 그 접근 가능한 부분) 끝에서만 일치시킨다.


\=
빈 문자열에 일치하지만 포인트에서만 일치시킨다.


\b
빈 문자열에 일치하지만 단어 시작이나 끝에서만 일치시킨다. 따라서 '
\bfoo\b
' 는 '
foo
'의 어떤 발생이든 구분된 단어로서 일치시킨다. '
\bballs?\b
'는 '
ball
' 또는 '
balls
'를 구분된 단어로서 일치시킨다.
'
\b
'는 버퍼 옆에 어떤 텍스트가 표시되든 버퍼의 시작이나 끝에서 일치시킨다.


\B
는 빈 문자열에 일치하지만 단어의 시작이나 끝에서는 일치시키지 않는다.


\<
는 빈 문자열에 일치하지만 단어의 시작에서만 일치시킨다. '
\<
' 는 단어 구성소(word-constituent) 문자가 따라올 때에만 버퍼의 시작에서 일치시킨다.


\>
는 빈 문자열에 일치하지만 단어의 끝에서만 일치시킨다. '
\>
' 는 단어 구성소 문자로 끝나는 내용일 경우에만 버퍼의 끝에서 일치시킨다.


\w
는 단어 구성소 문자라면 무엇에든 일치시킨다. 구분 테이블은 이것이 어떤 문자인지 결정한다. The Emacs Lisp Reference Manual의 "Syntax Tables" 절을 참고한다.


\W
단어 구성소 문자가 아닌 어떤 문자에든 일치시킨다.


\_<
빈 문자열에 일치시키지만 심볼의 시작에서만 일치시킨다. 심볼은 심볼 구성소 문자가 하나 또는 여러 개로 된 시퀀스다. 심볼을 구성하는 문자는 구문이 '
w
' 또는 '
_
'로 된 문자다. '
\_<
'는 심볼 구성소 문자가 뒤따를 때에만 버퍼의 시작에서 일치시킨다.


\_>
는 빈 문자열을 일치시키지만 부호의 끝에서만 일치시킨다. '
\_>
'는 내용이 심볼을 구성하는 문자로 끝날 때에만 버퍼의 끝에서 일치시킨다.


\sc
는 구문이 c 인 문자라면 모두 일치시킨다. 여기서 c 는 특정 구문 클래스를 지정하는 문자이므로 단어 구성소에 대한 '
w
', 공백에 대한 '
-
' 또는 '
', 일반 구두점에 '
.
'가 해당한다. The Emacs Lisp Reference Manual의 "Syntax Tables"절을 참고한다.


\Sc
는 구문이 c 가 아닌 문자라면 모두 일치시킨다.


\cc
범주 c 에 속하는 문자라면 모두 일치시킨다. 예를 들어 '
\cc
' 는 중국어 문자에 일치시키고, '
\cg
' 는 그리스어 문자에 일치시키는 식이다. 알려진 범주에 대한 설명은 M-x describe-categories RET 을 입력한다.


\Cc
범주 c 에 속하지 않는 문자라면 모두 일치시킨다.
단어와 구문에 관련된 구조체는 구문 테이블의 설정으로 제어된다. The Emacs Lisp Reference Manual의 "Syntax Tables"절을 참고한다.


정규 표현식 예제

Regexp의 예를 하나 소개할 것인데, 이는 Emacs가 문장의 끝에 따라오는 공백은 포함하지 않고 문장 끝을 인식하기 위해 기본값으로 사용하는 regexp와 비슷한 것이다:


[.?!][]\"')}]*


이는 연속으로 두 부분을 포함하는데, 한 가지는 마침표, '
?
', 또는 '
!
'에 일치하는 문자 집합이고, 다른 한 부분은 0번 또는 그 이상 반복된 닫힌 괄호(close-bracket), 큰 따옴표, 또는 괄호에 일치하는 문자 집합에 해당한다.


검색과 대, 소문자

사용자가 텍스트를 소문자로 명시할 경우 Emacs는 검색하는 텍스트의 대, 소문자를 무시하는 것이 보통이다. 따라서 사용자가 '
foo
'를 검색하도록 명시하면 '
Foo
'와 '
foo
' 역시 일치한다. Regexps 와 특정 문자 집합에서도 마찬가지로 작용하여, '
[ab]
'는 '
a
' 또는 '
A
' 또는 '
b
' 또는 '
B
'에 일치시킨다.


증분 검색 문자열 어디서든 대문자로 된 문자가 있으면 검색을 대, 소문자에 민감하게 만든다. 따라서 '
Foo
' 를 검색하면 '
foo
' 또는 '
FOO
' 를 찾지 못한다. 이는 문자열 검색은 물론이고 정규 표현식 검색에도 적용된다. 그리고 검색 문자열에서 대문자를 삭제하면 효과는 사라진다.


case-fold-search
변수를
nil
로 설정하면 대, 소문자를 포함해 모든 문자가 정확히 일치해야만 한다. 이는 per-buffer(버퍼당) 변수로, 변수를 수정하면 기본값을 사용자가 변경하지 않는 이상 현재 버퍼에만 영향을 미치는 것이 보통이다. 423 페이지의 33.2.3절 [로컬]을 참고한다. 이 변수는 비증분 검색에도 적용되는데, 대체 명령어는 물론이고 (103 페이지의 12.10절 [대체] 참고) 미니버퍼 히스토리 일치 명령어로 (32 페이지의 5.5절 [미니버퍼 히스토리] 참고) 실행되는 검색에도 적용된다.


증분 검색에서 M-c 라고 입력하면 해당 검색의 대, 소문자 민감성을 토글한다. 현재 증분 검색은 다음 검색을 넘어 확장되지 않지만 현재 검색에서 대문자로 된 글자를 제거하거나 추가하는 효과는 오버라이드한다.


몇 가지 연관된 변수들도 특정 명령어나 활동의 일치 및 검색에 대해 대, 소문자 민감성을 제어한다. 예를 들어
tags-case-fold-search
find-tag
에 대한 대, 소문자 민감성을 제어한다. 이러한 변수를 찾기 위해서는 M-x apropos-variable RET case-fold-search RET 을 실행한다.


대체 명령어

Emacs 는 찾아 바꾸기 연산을 수행하는 명령어를 몇 가지 제공한다. 단순한 M-x replace-string 명령어 외에도 패턴의 각 발생을 표시하고 대체할 것인지 묻는 M-% (
query-replace
)가 있다.


대체 명령어는 보통 포인트부터 버퍼의 끝까지 텍스트에 작업한다. 영역이 활성화되어 있으면 영역에 대신 작업한다(45 페이지의 8장 [마크] 참고). 기본 대체 명령어들은 검색 문자열(또는 regexp)을 하나의 대체 문자열로 대체한다.
expand-region-abbrevs
명령어를 이용해 몇 가지 대체를 동시에 실행하는 것도 가능하다(310 페이지의 26.3절 [축약어 확장하기] 참고).


증분 검색과 달리 대체 명령어들은 lax space 일치를 기본값으로 사용하지 않는다(92 페이지의 12.1.4절 [특수 Isearch] 참고). 대체에 lax space 일치를 활성화하려면
replace-lax-whitespace
변수를
t
로 변경한다. (이것은 대체 텍스트에 영향을 미치는 것이 아니라 대체할 텍스트를 Emacs가 찾는 방식에만 영향을 미친다.)


무조건적 대체

M-x replace-string RET string RET newstring RET

string 의 모든 발생을 newstring 으로 대체한다.


포인트 다음에 오는 '
foo
'를 모두 '
bar
'로 대체하려면 '
foo
' 와 '
bar
' 두 개의 인자를 둔 M-x replace-string 명령어를 사용한다. 대체는 포인트 다음 텍스트에서만 발생하므로 전체 버퍼에 적용하고 싶다면 우선 시작 부분으로 가야 한다. 버퍼의 끝까지 모든 발생이 대체되고, 대체를 버퍼의 부분으로 제한하려면 해당 부분 주변으로 영역을 활성화한다. 영역이 활성화되면 대체는 영역으로 제한된다(45 페이지의 8장 [마크] 참고).


replace-string
이 종료되면 마지막으로 대체된 발생에 포인트를 남겨둔다. 그리고 마크를 활성화하지 않은 채 포인트의 이전 위치를 (
replace-string
명령어가 발행된 위치) 마크 링으로 추가하는데, 다시 그곳으로 이동시키려면 C-u C-SPC 를 사용한다. 48 페이지의 8.4절 [마크 링]을 참고한다.


접두 인자는 단어 경계로 둘러싼 일치 결과로 대체를 제한한다.


대체 명령어에서 대, 소문자 민감도에 관한 상세한 내용은 104 페이지의 12.10.3절 [대체와 대, 소문자]를 참고한다.


Regexp 대체

M-x replace-string 명령어는 단일 문자열과 정확한 일치 결과를 대체한다. 이와 유사한 M-x replace-regexp 명령어는 명시된 패턴에 대한 일치 결과를 모두 대체한다.


M-x replace-regexp RET regexp RET newstring RET

regexp 에 일치하는 결과를 newstring 으로 대체한다.


replace-regexp
에서 newstring 은 상수일 필요가 없으며, regexp 에 의해 일치하는 부분 또는 전부를 의미할 수도 있다. newstring 에서 '
\&
'는 대체되는 전체 일치 결과를 의미한다. newstring 에서 d 가 숫자인 '
\d
'는 regexp 에서 d 번째 괄호로 표기된 그룹에 일치하는 결과를 의미한다. (이것을 "역 참조"라고 부른다.) '
\#
'는 이 명령어에서 이미 만들어진 대체의 계수를 의미하는 10진수 숫자다. 첫 번째 대체에서 '
\#
' 는 '
0
'을 의미하고, 두 번째는 '
1
'인 식으로 나아간다. 예를 들면 아래와 같다.


M-x replace-regexp RET c[ad]+r RET \&-safe RET


앞의 내용은 (예를 들자면) '
cadr
'을 '
cadr-safe
'로 대체하고, '
cddr
'을 '
cddr-safe
'로 대체한다.


M-x replace-regexp RET \(c[ad]+r\)-safe RET \1 RET


그리고 위는 역 변환(inverse transformation)을 실행한다. 대체할 텍스트에 '
\
'를 포함시키려면 '
\\
'를 입력해야 한다.


매번 대체 문자열의 일부를 수동으로 입력하길 원한다면 대체 문자열에 '
\?
'를 사용하라. 대체 시마다 미니버퍼에 대체 문자열을 편집하도록 요청하고 포인트를 '
\?
'가 위치했던 곳에 놓을 것이다.


아래에서는 특수화된 과제를 대상으로 하므로 Lisp 에 대한 지식을 요한다. 일반 독자들은 건너뛰어도 좋다.


Lisp 표현식을 이용해 대체 문자열의 부분을 계산할 수도 있다. 이를 위해서는 대체 문자열에 '
\
' 다음에 표현식을 쓴다. 대체마다 표현식의 값을 계산하여 인용 부호 없이 텍스트로 변환하고 (문자열일 경우 문자열의 내용을 사용함을 의미), 이를 표현식 자체를 대신해 대체 문자열에 사용한다. 표현식이 부호(symbol)일 경우 부호명 다음에 대체 문자열에 하나의 공백과 함께 부호명이 포함되므로 둘 다 값으로 대체된다.


그러한 표현식 안에서는 몇 가지 특수 시퀀스를 사용할 수 있다. '
\&
'와 '
\n
'는 여기서도 보통처럼 문자열로서 전체 일치 결과와 문자열로서 하위 일치 결과를 의미한다. n 은 여러 개의 숫자가 될 수 있고, 하위 표현식 n 이 일치하지 않으면 '
\n
'의 값은
nil
이다. '
\#&
'와 '
\#n
'를 이용해 숫자로서 일치 결과를 나타낼 수도 있다(이는 일치 또는 하위 일치가 숫자 형태를 가질 때 유효하다.). 이 때 '
\#
'는 이미 완성된 대체의 개수를 의미한다.


따라서 우리 예제를 다시 이용해 'x'와 'y'를 교환할 경우 아래와 같이 실행할 수 있겠다:


M-x replace-regexp RET \(x\)\+y RET
\,(if \1 "y" "x") RET


'
\,
'에 대한 대체 문자열을 계산하는 데에는 format 함수가 유용하게 사용되곤 한다(The Emacs Lisp Reference Manual 의 "Formatting Strings"절 참고). 가령 '
ABC00042
'와 같이 연속으로 숫자를 매긴 문자열을 73부터 80번 열까지 (이미 차지하지 않는 경우에 한해) 추가하기 위해서는 다음을 이용할 수 있다.


M-x replace-regexp RET ",\{0,72\}$ RET
\,(format "7„-72sABC0/„05d" \& \#) RET


대체 명령어와 대, 소문자

대체 명령어의 첫 번째 인자가 모두 소문자일 경우,
case-fold-search
nil
이 아닐 때 한해 명령어는 대체할 발생을 검색하면서 대, 소문자를 무시한다.
case-fold-search
nil
로 설정되면 대, 소문자는 모든 검색에서 중요해진다.


또한 newstring 인자가 모두 혹은 부분적으로 소문자라면 대체 명령어는 각 발생마다 대, 소문자 패턴을 유지하려고 시도한다. 따라서


M-x replace-string RET foo RET bar RET


위의 명령어는 소문자로 된 '
foo
'를 소문자 '
bar
'로, 대문자 '
FOO
' 를 '
BAR
'로, 대문자로 시작하는 '
Foo
' 를 '
Bar
' 로 대체한다. (
replace-string
은 이 세 가지 방법, 즉 모두 소문자, 모두 대문자, 첫 글자만 대문자로 표기하는 방법만 구별한다.)


대체 문자열에 대문자가 사용될 경우 텍스트가 삽입될 때마다 대문자로 유지된다. 대문자로 된 글자가 첫 번째 인자에 사용되면 두 번째 인자는 대, 소문자 변환 없이 정확히 주어진 대로 대체된다. 마찬가지로
case-replace
또는
case-fold-search
nil
로 설정되면 대, 소문자 변환 없이 대체가 이루어진다.


쿼리 대체

M-% string RET newstring RET

string 발생 일부를 newstring 으로 대체한다.


C-M-% regexp RET newstring RET

regexp 일치 결과 일부를 newstring 으로 대체한다.


'
foo
'의 발생 중 일부만 '
bar
'로 변경하고 싶다면 M-% (
query-replace
)를 사용한다. 이 명령어는 '
foo
'의 발생을 하나씩 찾아서 각 발생을 표시한 후 대체할 것인지 질문한다.
query-replac
e 는 쿼리 외에도
replace-string
과 같은 기능을 하기도 한다(103 페이지의 12.10.1절 [무조건적 대체] 참고). 특히
case-replace
nil
이 아닐 때는 평소대로 대, 소문자를 유지한다(104 페이지의 12.10.3절 [대체와 대, 소문자] 참고). 수치적 인자는 단어 구분 문자로 바인딩된 발생만 고려할 것을 의미한다. 음으로 된 접두 인자는 역방향으로 대체한다.


C-M-% 는 regexp 검색과 대체를 실행한다(
query-replace-regexp
). 이는
query-replace
처럼 질의(query)한다는 점만 제외하면
replace-regexp
와 같이 작용한다.


이러한 명령어들은
query-replace
face를 이용해 현재 일치 결과를 강조한다. 증분 검색과 마찬가지로
lazy-highlight
를 이용해 다른 일치 결과를 강조한다(90 페이지의 12.1절 [증분 검색] 참고). 기본적으로
query-replace-regexp
는 미니버퍼에서 현재 일치 결과에서 대체된 대체 문자열을 표시할 것이다. 특수 시퀀스 '
\&
'와 '
\n
'을 확장되지 않은 채로 유지하고 싶다면
query-replace-show-replacement
변수를 맞춤화한다.


문자열이나 regexp에 대한 일치 결과를 표시할 때 입력할 수 있는 문자는 다음과 같다:


SPC 발생을 newstring 으로 대체한다.


DEL 이번 것을 대체하지 않고 다음 발생으로 건너뛴다.


, (콤마)

현재 발생을 대체하고 결과를 표시한다. 사용자에게 다음에 무엇을 실행할 것인지 알려주는 또 다른 입력 문자를 질문할 것이다. 이미 대체가 실행되었으므로 이 상황에서 DELSPC 는 동일하여 둘 다 다음 발생으로 이동한다.
대체된 텍스트를 수정하려면 이 시점에서 C-r 을 입력한다(아래 참고). C-x u 를 입력하면 대체를 실행 취소할 수도 있는데, 이는
query-replace
를 종료하므로 추가로 대체를 원한다면 C-x ESC ESC RET 를 이용해 재시작한다(34 페이지의 5.6절 [반복] 참고).


RET 더 이상 대체를 실행하지 않고 종료한다.


. (마침표) 이번 발생을 대체한 후 더 이상 발생을 검색하지 않고 종료한다.


! 다시 묻지 않고 나머지 발생을 모두 대체한다.


Y (대문자) 다중 버퍼 대체에서 나머지 모든 버퍼에 나머지 모든 발생을 대체한다(선택된 파일에 대해 쿼리 대체를 실행하는 Dired
Q
명령어처럼). 이 질문을 비롯해 잇따른 질문에 더 이상 사용자 상호작용 없이 "yes" 라고 답한다.


N (대문자) 현재 버퍼에서 나머지 발생을 대체하지 않고 미니버퍼 대체에서 다음 버퍼로 건너뛴다. 이 질문에 "no" 라고 답을 하고, 현재 버퍼에 대한 질문을 포기하며, 시퀀스에서 다음 버퍼로 계속한다.


^ 사용자가 실수로 변경하거나 다시 검사하길 원할 경우 이전 발생(또는 이전에 발생하였던)의 위치로 돌아간다.


C-r 발생을 편집할 필요가 있을 경우 newstring 으로 대체하는 대신 재귀적 편집 수준으로 들어간다. 완료되면 C-M-c 를 이용해 재귀적 편집 수준을 종료하여 다음 발생으로 나아간다. 404 페이지의 31.10절 [재귀적 편집]을 참고한다.


C-w 발생을 삭제한 후 C-r 에서와 마찬가지로 재귀적 편집에 들어간다. 재귀적 편집을 이용해 삭제된 문자열 발생을 대체하기 위한 텍스트를 삽입한다. 완료되면 C-M-c 를 이용해 재귀적 편집 수준을 종료하여 다음 발생으로 나아간다.


e 미니버퍼에서 대체 문자열을 편집한다. RET 을 입력하여 미니버퍼를 종료하면 미니버퍼 내용이 패턴의 현재 발생을 대체한다. 향후 발생에 대한 새로운 대체 문자열이 되기도 한다.


C-l 화면을 다시 표시한다. 이후 사용자는 다른 문자를 입력하여 이 발생을 어떻게 할 것인 것 명시한다.


C-h 이러한 옵션을 요약하는 메시지를 표시한다. 이후 다른 문자를 입력하여 이 발생을 어떻게 할 것인지 명시한다.


몇 가지 다른 문자는 위에 열거된 것과 동일한데, 가령
y
,
n
,
q
SPC, DEL, RET 와 동일하다.


이 외에 다른 어떤 문자도
query-replace
를 종료하고, 이후 키 시퀀스의 일부로 다시 읽힌다. 따라서 C-k 를 입력하면
query-replace
를 종료한 후 행 끝까지 제거한다(kill).


query-replace
를 종료한 후 다시 시작하려면
query-replace
를 반복하는 C-x ESC ESC 를 사용해야 하는데, 미니버퍼를 이용해 인자를 읽었기 때문이다. 34 페이지의 5.6절 [반복]을 참고한다.


search-invisible
옵션은
query-replace
가 보이지 않는 텍스트를 어떻게 취급하는지 결정한다. 220 페이지의 [개요 검색]을 참고한다.


선택된 파일에서 쿼리 대체를 실행하는 Dired
Q
명령어에 대한 내용은 320 페이지의 27.7절 [파일 작업하기]를 참고한다. 파일명에서 regexp 일치 결과를 대체하는 파일의 재명명, 복사, 또는 연결을 위한 Dired 명령어의 사용은 323 페이지의 27.9절 [파일명 변형]을 참고한다.


그 외 Search-and-Loop 명령어

정규 표현식에 일치하는 결과를 찾는 다른 명령어들도 존재한다. 이러한 명령어들은 모두 패턴이 대문자를 포함하지 않고
case-fold-search
nil
이 아닐 경우 일치 결과에서 대, 소문자를 무시한다.
occur
와 그 변형체 외에 모든 명령어들은 포인트부터 버퍼 끝까지 텍스트에 적용되고, 영역이 활성화되어 있다면 영역에 적용된다.


M-x multi-isearch-buffers RET으로 끝나는 하나 또는 그 이상의 버퍼 이름을 요청한 후 그러한 버퍼에서 다중 버퍼 증분 검색을 시작한다. (한 버퍼에서 검색이 실패한 후 다시 C-s 를 사용하면 다음으로 명시된 버퍼에서 검색을 실행하는 식으로 진행된다.) 접두 인자를 이용해 regexp를 요청하고, 해당 regexp에 일치하는 버퍼에서 다중 버퍼 증분 검색을 시작한다.


M-x multi-isearch-buffers-regexp 증분 regexp 검색을 실행한다는 점만 제외하면
multi-isearch-buffers
와 동일하다.


M-x occur Regexp를 요청하고, 버퍼 내에서 일치 결과를 포함하는 각 행을 표시하는 목록을 표시한다. 버퍼의 일부로 검색을 제한하려면 해당 부분으로 좁힌다(73 페이지의 11.5절 [좁히기] 참고). 수치적 인자 n 은 일치하는 행마다 전후로 n 개의 컨텍스트 행이 표시되도록 명시한다.

*Occur*
버퍼에서는 각 엔트리마다 클릭하거나 그 곳으로 포인트를 옮겨 RET 를 입력하면 버퍼에서 검색을 진행한 위치로 방문한다. oC-o 는 다른 창에 일치 결과를 표시하고, C-o 는 그것을 선택하지 않는다. 아니면 C-x ' (
next-error
) 명령어를 이용해 하나씩 발생(occurrence)을 방문할 수 있다(262 페이지의 24.2절 [컴파일 모드] 참고).
*Occur*
버퍼에 e 라고 입력하면 Occur Edit 모드로 전환되어 엔트리에 이루어진 편집 내용은 처음 시작된(originating) 버퍼의 텍스트에도 적용된다. Occur 모드로 돌아가려면 C-c C-c 를 입력한다.
M-x list-matching-lines 명령어는 M-x occur 와 동일하다.


M-s o 마지막 증분 문자열 검색의 검색 문자열을 이용해
occur
를 실행한다. 증분 검색이 활성화되어 있으면 M-s o 를 실행할 수도 있는데, 이는 현재 검색 문자열을 사용한다.


M-x multi-occur 다중 버퍼를 통해 검색이 가능하다는 점만 제외하면
occur
와 같다. 사용자에게 버퍼 이름을 하나씩 명시하도록 요청한다.


M-x multi-occur-in-matching-buffers 방문한 파일명에 일치하는 정규 표현식이 검색할 버퍼를 명시한다는 점만 제외하면
multi-occur
와 비슷하다. 접두 인자를 이용하면 정규 표현식이 파일명 대신 버퍼 이름에 일치하도록 마련할 수 있다.


M-x how-many 사용자에게 regexp를 요청하고, 포인트 다음 버퍼에서 그에 일치하는 결과의 개수를 출력한다. 영역이 활성화되어 있으면 영역에 대신 적용된다.


M-x flush-lines 사용자에게 regexp를 요청하고, 포인트 이후의 텍스트에 실행하여 그에 일치하는 결과를 포함하는 각 행을 삭제한다. 포인트 이후부터 시작되는 일치 결과를 현재 행이 포함할 경우 현재 행을 삭제한다. 영역이 활성화되어 있다면 영역에 대신 실행하고, 영역에 행의 일부가 포함되어 있고 그 행이 영역에 전체가 포함된 일치 결과를 포함한다면 행은 삭제된다.

일치 결과가 행들 간 나뉘어져 있다면
flush-lines
를 이용해 해당 행들을 모두 삭제한다. 다음 일치 결과의 검색을 시작하기 전에 행을 삭제하므로 또 다른 일치 결과가 끝나는 행과 동일한 행에서 시작하는 일치 결과는 무시한다.


M-x keep-lines 사용자에게 regexp를 요청하고, 포인트 이후의 텍스트에 실행하여 그에 일치하는 결과를 포함하지 않는 각 행을 삭제한다. 포인트가 행의 시작에 위치하지 않는다면 이 명령어는 항상 현재 행을 유지한다. 영역이 활성화되어 있다면 명령어는 영역에 대신 실행되고, 영역에 부분적으로만 포함되어 있는 행은 절대 삭제하지 않는다(행을 끝내는 새 행은 그 행의 일부로 간주된다.). 일치 결과가 행들에 걸쳐 나뉘어져 있다면 이 명령어는 그 행들을 모두 유지한다.


Notes