【问题标题】:The smallest matching expression on the left?左边最小的匹配表达式?
【发布时间】:2012-09-06 16:49:55
【问题描述】:

这是我所拥有的:

{a} {b} over {c} {d}
{a} {{b} over {c}} {d}

(我有一些文字,它有这样的表达方式)我想将两者都转换为:

{a} \frac{b}{c} {d}

这是我最好的选择:

(goto-char (point-min))
(while (search-forward-regexp "{+?\\(.+?\\)} +over +{\\(.+?\\)}+?" nil t) 
  (replace-match (concat "\\\\" "frac{\\1}{\\2}") t nil))

但它不起作用。我明白了:

\frac{a} {b}{c} {d}
\frac{a} {{b}{c}} {d}

分别。

问题是——我的正则表达式尽可能多地在左侧捕获。虽然我需要它尽可能少地捕获。

编辑

接受的答案不适用于更复杂的情况(我也需要):

{d^{2} q} over {d t^{2} }
{{d^{2} q} over {d t^{2} }}

(因为嵌套)

这是解析器的工作版本(代码中有趣的部分从while开始):

(defun over2frac ()
  (interactive)
  (let (start end
        (case-fold-search nil)
        lStart lEnd lStr
        rStart rEnd rStr)
    (if (use-region-p)
        (progn (setq start (region-beginning)) ;; then
               (setq end (region-end)))
      (progn (setq start (line-beginning-position)) ;; else
             (setq end (line-end-position))))
    (save-restriction 
      (narrow-to-region start end)
      (goto-char (point-min))

      (while (search-forward-regexp "{\\(.+\\)}\s*over\s*{\\(.+?\\)}" nil t) 

        ;; r:
        (goto-char (match-beginning 2))
        (backward-char 1)
        (setq rStart (point))
        (forward-sexp)
        (setq rEnd (point))
        (setq rStr (buffer-substring-no-properties rStart rEnd))

        ;; l:
        (goto-char (match-end 1))
        (forward-char)
        (setq lEnd (point))
        (backward-sexp)
        (setq lStart (point))
        (setq lStr (buffer-substring-no-properties lStart lEnd))

        (delete-region lStart rEnd)
        (insert "\\" "frac" lStr rStr)
        ))))

由于它使用forward-sexpbackward-sexp -- 并且没有定义syntax-table -- 它只能在适当的模式下工作(例如rst-modetext-mode -- 而不是emacs-lisp-mode。对于它给出的上述复杂示例:

\frac{d^{2} q}{d t^{2} }
{\frac{d^{2} q}{d t^{2} }}

编辑 2

(defun backslash-func--args-on-both-sides (Find Replace)
  (goto-char (point-min))
  (while (search-forward-regexp (concat "\\([^{]+\\)}\s*" Find "\s*{\\([^}]+\\)") nil t) 

    ;; r:
    (goto-char (match-beginning 2))
    (backward-char 1)
    (setq rStart (point))
    (forward-sexp)
    (setq rEnd (point))
    (setq rStr (buffer-substring-no-properties rStart rEnd))

    ;; l:
    (goto-char (match-end 1))
    (forward-char)
    (setq lEnd (point))
    (backward-sexp)
    (setq lStart (point))
    (setq lStr (buffer-substring-no-properties lStart lEnd))

    ;; s:
    (goto-char lStart)
    (if (looking-back "{") 
        (setq lStart (1- (point))))

    (goto-char rEnd)
    (if (looking-at "}")
        (setq rEnd (1+ (point))))

    (delete-region lStart rEnd)
    (insert "\\" Replace lStr rStr))

  (goto-char (point-min))
  (while (search-forward-regexp (concat "\\([0-9a-zA-Z_^]+\\)\s*" Find "\s*\\([0-9a-zA-Z_^]+\\)") nil t) (replace-match (concat "\\\\" Replace "{\\1}{\\2}") t nil))
  )

这会转换两个东西:

{d^{2} q} over {d t^{2} }
{{d^{2} q} over {d t^{2} }}

\frac{d^{2} q}{d t^{2} }

我在这里不使用let,因为所有的变量都已经是本地的了——而defun 本身在另一个defun 中。 Full code.

【问题讨论】:

  • 当然,只写两个正则表达式会更容易,因为一个只需要对另一个进行轻微修改。

标签: regex math emacs latex libreoffice


【解决方案1】:

使用这个表达式:http://regex101.com/r/kY8jY5

/{+([^{}]+)}\s*over\s*{([^{}]+)}+/g

表达式应该与emacs兼容。

替换为:

\frac{\1}{\2}

注意:我不确定你是否在 emacs 中使用 \1$1

【讨论】:

  • 在 emacs 中是:(while (search-forward-regexp "{+\\([^{}]+\\)}\s*over\s*{\\([^{}]+\\)}+" nil t) (replace-match (concat "\\\\" "frac{\\1}{\\2}") t nil))。使用{(.+?)} 而不是([^{}]+),这都是我的坏习惯。
【解决方案2】:

通过在正则表达式的开头添加一个贪婪的*,并将其放在替换的首位:

(goto-char (point-min))
(while (search-forward-regexp "\\(.*\\){+?\\(.+?\\)} +over +{\\(.+?\\)}+?" nil t) 
  (replace-match (concat "\\1\\\\" "frac{\\2}{\\3}") t nil))

我得到它来制作这个:

{a} \frac{b}{c} {d}
{a} {\frac{b}{c}} {d}

我不确定是否有任何方法可以摆脱多余的 {}...

【讨论】:

  • 无论如何——我喜欢在左边尽可能多地捕捉的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-27
  • 1970-01-01
  • 1970-01-01
  • 2018-07-16
  • 1970-01-01
  • 2016-06-12
相关资源
最近更新 更多