Emacs查询替换正则表达式反转

3

有没有现成的软件包可以在query-replace-regexp执行时指定子表达式进行替换?

例如,给定以下内容:

var foo1 = blah( properties, property_id);

var foo2 = blah(properties, property_id );

var foo3 = blah(  properties, property_id      );

我希望去掉大括号周围的填充。

通常的方法是将您想要保留的位子分组,并组装一个替换。

搜索:

\(var .* = blah\s-*(\)\s-*\(.*?\)\s-*\()\)

替换:

\1\2\3

然而,对于我想要删除的位进行分组的正则表达式似乎比反过来更容易。像这样:

var .* = blah\s-*(\(\s-*\).*?\(\s-*\))

我将从中得到两个子组。我要如何定位它们以进行替换?
编辑:我正在寻求一种交互式的方式来“倒转”给定的正则表达式。因此,界面类似于query-replace-regexp 1. 输入正则表达式 2. 输入第一个组的替换内容 3. 输入第二个组的替换内容
2个回答

1

我认为这个变体应该可以工作:

(defun remove-padding ()
  (interactive)
  (while (search-forward-regexp
          "var .* = [a-zA-Z_]+\\s-*(\\(\\s-*\\).*?\\(\\s-*\\))"
          nil t)
    ;; Replace the 2 subexpressions with nothing
    (replace-match "" nil t nil 2)
    (replace-match "" nil t nil 1)))

然而,根据您的使用情况,您可能还需要考虑使用类似indent的工具。

编辑:下面是一个非常简单的交互式版本。函数query-replace-regexp非常复杂,我没有尝试复制它的所有功能。

(require 're-builder)
(defun query-replace-subexpressions (regexp replacements)
  "REPLACEMENTS need to be in reverse order if passed from lisp!"
  ;; Read the correct number of subexpressions
  (interactive
   (let* ((re (read-from-minibuffer "Query replace subexps: "))
          (num-subexps (reb-count-subexps re))
          (replacement-list nil)
          (replacements (dotimes (rep num-subexps)
                          (setq replacement-list
                                (cons
                                 (read-from-minibuffer
                                  (format "Replace subexpression %s with: " rep))
                                 replacement-list)))))
     (list re replacement-list)))
  ;; Search
  (let ((len (length replacements)))
    (while (search-forward-regexp regexp nil t)
      (replace-highlight (match-beginning 0) (match-end 0)
                         (point-min) (point-max) regexp
                         t case-fold-search)
      ;; Query
      (when (save-match-data (y-or-n-p "Replace this occurrence? "))
        ;; Make all the replacements
        (dotimes (i len)
          (replace-match (nth i replacements) nil nil nil (- len i)))))
    (replace-dehighlight)))


;; Test it out below
(query-replace-subexpressions
 "var .* = [a-zA-Z_]+\\s-*(\\(\\s-*\\).*?\\(\\s-*\\))"
 '("" ""))

var foo1 = blah(properties, property_id    );

var foo2 = blah (properties, property_id );

var foo3 = blah( properties, property_id      );

我澄清了问题。 "交互式" 是关键。 - event_jr
这回答了我的问题。我还制作了一个钩子版本,下面连接到query-replace-regexp - event_jr

1

我已经成功地钩入了github上的query-replace-regexp

以下是粘贴内容,以防链接失效:

;; -*- lexical-binding: t -*-

(provide inverted-replace)

(require 're-builder)
(require 'parallel-replace)

(defun inverted-replace-generate-replacement (from to)
  "invert result of current match (match-string 0)"
  (let ((string (match-string 0))
        (count (reb-count-subexps from))
        (replacements (parallel-replace-read-list to)))
    (save-match-data
      (string-match from string)
      (dotimes (i count)
        (setq string (replace-match (nth i replacements) nil nil string (- count i)))))
    string))

(defun inverted-replace-regexp (from to)
  (interactive (destructuring-bind (from to _)
                   (query-replace-read-args "inverted-replace-regexp: " t)
                 (list from to)))
  (query-replace-regexp from
                        (quote (replace-eval-replacement
                                replace-quote
                                (inverted-replace-generate-replacement from to)))
                        nil (and (and transient-mark-mode mark-active)
                               (region-beginning))
                        (and (and transient-mark-mode mark-active) (region-end))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接