Emacs Lisp: Find Replace String in Buffer

By Xah Lee. Date: . Last updated: .

Search and Find Replace Functions

These search functions are used for search text, do find replace, and also move cursor to where a pattern occur:

The forward versions place cursor at end of match. The backward versions place cursor at begin of match.

(search-forward STRING &optional BOUND NOERROR COUNT)
Move cursor forward by searching for given string. Cursor stops at end of matched string.
Also search-backward. Cursor stops at beginning of matched string.
;; move cursor to the location of cat
(search-forward "cat")
(re-search-forward REGEXP &optional BOUND NOERROR COUNT)
Move cursor forward by searching for regex pattern. Cursor stops at end of matched pattern. Return the new position.
Also re-search-backward. Cursor stops at beginning of matched string.
[see Emacs: Regular Expression]
;; move cursor to the end of a html closing tag
(re-search-forward "</[a-z0-9]+>")

Find Replace Text in Buffer

Typical way to do string replacement in current buffer:

(let ((case-fold-search nil))

  (goto-char (point-min))
  (while (search-forward "myStr1" nil t)
    (replace-match "myReplaceStr1"))

  (goto-char (point-min))
  (while (search-forward "myStr2" nil t)
    (replace-match "myReplaceStr2"))

  ;; repeat for other string pairs


Case Sensitivity in Search

To control the letter case of search, locally set case-fold-search to t or nil. By default, it's t.

(let (
      (case-fold-search nil) ; case sensitive search
  ;; find replace code here

Case Sensitivity in Replacement

To control letter case of the replacement, use the optional arguments in replace-match function.


Use t for FIXEDCASE.

Match Data

Most functions that take a regex argument, after being called, will save/modify info in “match data”, such as caputured groups, or begin/end positions of the captured pattern, or whole matched pattern.

Match data can be accessed by the function match-data, and other functions.

However, elisp provide many more direct function to extract data stored in match-data.

The most useful are match-string, match-beginning, match-end.

Get Match String

Whenever you call regex functions such as re-search-forward, string-match, replace-regexp-in-string, the captured text is stored in match-string.

(match-string NUM &optional STRING)
Return string of text matched by last search. NUM specifies which parenthesized expression in the last regexp. 0 is the whole pattern. STRING should be given if the last search was by string-match on STRING.
;; get the id
(re-search-forward "id=\\([a-z0-9]+\\)" )
(message "%s" (match-string 1 ))

;; id=172

Get Begin/End Positions

match-beginning and match-end return the begin and end positions of the matched string.

;; get the begin/end positions of the whole regex match
(setq pos1 (match-beginning 0))
(setq pos2 (match-end 0))

Find Replace in a Region Boundary

If you need to do find replace on a region only, wrap the code with save-restriction and narrow-to-region. Example:

(save-restriction (narrow-to-region pos1 pos2) body )

;; idiom for string replacement within a region
  (narrow-to-region pos1 pos2)

  (goto-char (point-min))
  (while (search-forward "myStr1" nil t)
    (replace-match "myReplaceStr1"))

  ;; repeat for other string pairs

WARNING: Boundary Change After Insert/Remove text

Whenever you work in a region, remember that the boundaries of the text that you are interested is changed when you add or remove text in that region. For example, suppose {p1, p2} is the boundary of some text you are interested. After doing some change there, suppose you want to do some more change. Don't just call (something-region p1 p2) again, because p2 is no longer the correct boundary.

A good solution is to use (narrow-to-region p1 p2) and use (point-min) and (point-max) for boundary, once you narrowed.

Find Replace Multiple Pairs

If you need to find replace multiple pairs frequently, see: Emacs: Xah Replace Pairs, xah-replace-pairs.el.

Emacs Regular Expression

Regex in Emacs Lisp

Practical Elisp ⭐

Writing Command

Text Processing

Get User Input


Writing Script