This page shows you how to use a elisp function in your regex replacement. This lets you do transformation of the matched text. For example, replacing “_” to space, or insert timestamp, current file name, in your replacement text.
Suppose you have 5 thousand HTML files, and many Wikipedia links like the following:
① <a href="…/Emacs_Lisp">Emacs Lisp</a>
② <a href="…/Emacs_Lisp">Emacs_Lisp</a>
③ <a href="…/Emacs_Lisp">http://en.wikipedia.org/wiki/Emacs_Lisp</a>
We want format 2 and 3 to be replaced with format 1, but on case-by-case basis. (case-by-case because sometimes you do not want regex replace to be done for all matches.)
For simplicity, let's say i just want to replace format 2 to format 1 on a case by case basis.
In emacs 22, there's a new feature that allows you use a function as your replacement string.
In the replace string prompt, give
\,(‹function name›), where ‹function name› is your elisp function.
The function needs no argument. Its return value is used as the replacement string.
The task here is to write the replacement function.
Let's say our function will be named ff. ff will take 1 input that's the matched text, then replace
_ by space, then return the new text.
Here's our function template:
(defun ff () "temp function. Returns a string based on current regex match." ; 1. get the matched text ; 2. transform the matched text ; 3. returns the transformed text )
How do we actually get the matched text? Here's the solution:
(defun ff () "return matched text with underscore replaced by space." (replace-regexp-in-string "_" " " (match-string 1)) )
(match-string 1) gives you the first captured string. (“1” is for 1st captured pattern, “2” for 2nd captured pattern. “0” is the entire match.). The
replace-regexp-in-string is used to transform the text.
(To make emacs aware of
ff, select the whole definition, then call
So, with this function written, we can call
dired-do-query-replace-regexp, then give this pattern:
And the replacement expression would be:
and we are all done.
This function can be of general use. Whenever you need to replace text patterns with complicated heuristics, you can base your replacement function on the above code.
Here's the actual replacement function i used for this job:
(defun wikipedia-link-replacement () "Returns a canonical form of Wikipedia link from a regex match. The regex to be used for this function is: <a href=\"http://\\(..\\)\\.wikipedia.org/wiki/\\([^\"]+\\)\">\\(\\([-.A-Za-z0-9]+_\\)+[-.A-Za-z0-9]+ ?\\)</a> To use this function, call `query-replace-regexp', then in the replacement prompt give: \\,(wikipedia-link-replacement) " (let (langCode articlePath linkText linkText2 returnText) (setq langCode (match-string 1)) (setq articlePath (match-string 2)) (setq linkText (match-string 3)) (setq linkText2 (replace-regexp-in-string "_" " " articlePath)) (setq returnText (concat "<a href=\"http://" langCode ".wikipedia.org/wiki/" articlePath "\">" linkText2 "</a>" )) returnText ) )
Emacs is beautiful.
I need to find all text of the form:
(info "(emacs) Option Index")
and change it into this form:
<a href="../emacs_manual/Option-Index.html">(info "(emacs) Option Index")</a>
Here's the regex i use:
(info "(emacs) \([^"]+?\)")
Here's the replacement code:
Here's the elisp code:
(defun ff () "temp" (interactive) (let (matchedText url replaceText anchorText) (setq matchedText (match-string 1 ) ) (setq replaceText (replace-regexp-in-string " " "-" matchedText)) (setq url (concat "../emacs_manual/" replaceText ".html" ) ) (setq anchorText (concat "(info \"(emacs) " matchedText "\")" ) ) (concat "<a href=\"" url "\">" anchorText "</a>") ))
Here are more examples of using a function as replacement string.