replace-regex从camel case函数名中删除第一个元素

时间:2014-03-14 13:41:24

标签: regex emacs elisp

我有这样的代码:

<?= $this->Article->getShowComments(); ?>

并需要将其转换为

{{ Article.showComments }}

使用简单的正则表达式,一切都很简单:异常.getFooBar.fooBar,我如何在Elisp中执行此操作,是否有像使用javascript中的函数替换?

2 个答案:

答案 0 :(得分:2)

case-fold-search设为nil

M-x set-variable RET case-fold-search RET nil

现在,使用以下命令进行转换:

M-x replace-regexp RET \_<\(?:[a-z0-9]\|\s_\)+\([A-Z]\) RET \,(downcase \1)

第一个参数是要搜索的正则表达式,第二个参数是替换文本。

regexp有点复杂,但基本上匹配一个符号开头(\_<是符号start),带有小写字母或数字([a-z0-9])或非单词符号字符({{1} }),后跟一个大写字母\s_。第一个非分组括号[A-Z]只对or-operator \(?:…\)进行分组。

大写字母周围的第二个括号是分组,它会创建“引用”\|以用于替换文本。

我们将匹配的大写字母的引用包装到函数\1中,以将其转换为小写。替换文本中的downcase告诉Emacs,以下文本是要评估的正确性别,而不仅仅是一个简单的字符串。

编辑1)此RE的\,变体可能更容易理解:

rx

很遗憾,您无法在(and symbol-start (one-or-more (or (any "a-z" "0-9") (syntax symbol))) (group-n 1 (any "A-Z")) 中使用RX表达式。

修改2) replace-match仅供仅限交互式使用。它不应该以非交互方式使用,即来自Emacs Lisp。值得注意的是,当以非交互方式使用时,此函数不会编译替换文本,因此特殊replace-regexp转义将无效

从Emacs Lisp中,使用\,re-search-forward

replace-match

确保将其包装在(let ((case-fold-search nil) (regexp (rx symbol-start (one-or-more (or (any "a-z" "0-9") (syntax symbol))) (group-n 1 (any "A-Z"))))) (while (re-search-forward regexp nil 'no-error) (replace-match (downcase (match-string 1)) 'fixed-case 'literal))) 中以使其在正确的缓冲区上运行。

答案 1 :(得分:1)

这是我在阁楼里得到的东西:

(defun CamelCase->underscore (str)
  (mapconcat 'identity (CamelCase->list str) "_"))

(defun CamelCase->list (str)
  (let ((case-fold-search nil)
        (pos 0)
        words)
    (while (string-match ".[^A-Z]*" str pos)
      (let ((word (downcase (match-string-no-properties 0 str))))
        (if (> (length word) 1)
            (push word words)
          (setq words (cons (concat (car words) word)
                            (cdr words)))))
      (setq pos (match-end 0)))
    (reverse words)))
(CamelCase->underscore "getShowComments")
;; => "get_show_comments"

只需要适应你的情况。

以下是改编:

(defun CamelCase->something (str)
  (let ((case-fold-search nil)
        (pos 0)
        words)
    (while (string-match ".[^A-Z]*" str pos)
      (let ((word (match-string-no-properties 0 str)))
        (if (> (length word) 1)
            (push word words)
          (setq words (cons (concat (car words) word)
                            (cdr words)))))
      (setq pos (match-end 0)))
    (setq words (cdr (reverse words)))
    (mapconcat 'identity
               (cons (downcase (car words)) (cdr words))
               "")))