How to search/replace expressions with parantheses

2019-05-10 12:27发布

问题:

I have a bit of Latex code with lots of maths expressions enclosed in \mathrm{}. I'd like to remove the \mathrm{} code around the expressions, preferrably using emacs. For example, I'd like to substitute

\mathrm{\gamma \cdot x_0}

with

\gamma \cdot x_0

Removing \mathrm{ only is easy, but I also need to remove the closing bracket. How can I do this in emacs?

Many thanks,

Enno

回答1:

You can use back references to tackle this problem. Run

M-x query-replace-regexp

and enter \\mathrm{\([\a-z0-9_ ]+\)} at the first prompt, \1 at the second prompt.

The default keybinding for query-replace-regexp is C-M-%.

The \1 is a back reference to the first parenthesized group, \([\a-z0-9_ ]+\), in the regexp to replace. This group targets the content between the curly brackets. So what you are saying is that for any occurrence of the regexp to replace you would only like to keep that content.


More info on replacing regular expressions can be found here or in the corresponding info node of the Emacs manual.



回答2:

The command query-replace-regexp is quite flexible. You can set replace-re-search-function to your own search function. On this basis the following lisp code defines a new command query-replace-re+sexp which searches for a regular expression but includes the trailing sexp into the match.

After evaluating the defun below you can use M-x query-replace-re+sexp as query-replace function. In your example, input as "from"-string \\\\mathrm and as "replace-with"-string \\1. There, the expression \\1 refers to the additional subexpression which results from the trailing sexp (without delimiters).

(defun re+sexp-search-forward (regexp bound noerror)
  "Search forward for REGEXP (like `re-search-forward')
but with appended sexp."
  (when (re-search-forward regexp bound noerror)
    (let ((md (match-data))
      bsub esub)
      (setq bsub (1+ (scan-sexps (goto-char (scan-sexps (point) 1)) -1))
        esub (1- (point)))
      (setcar (cdr md) (set-marker (make-marker) (point)))
      (setq md (append md (list (set-marker (make-marker) bsub)
                (set-marker (make-marker) esub))))
      (set-match-data md)
      (point))))

(defun query-replace-re+sexp ()
  "Like `query-replace-regexp' but at each match it includes the trailing sexps
into the match as an additional subexpression (the last one)."
  (interactive)
  (let ((replace-re-search-function 're+sexp-search-forward)) (call-interactively 'query-replace-regexp)))

This should be a quite nice feature. Not only for the replacement of LaTeX constructs like

\mathrm{\frac{\gamma}{x_0}}

with

\frac{\gamma}{x_0}

but also for replacements in program texts. For an example the replacement of function calls like

doSomethingUseless(x+somethingUseful(y))

with

x+somethingUseful(y)