如何以编程方式创建一个正则表达式来匹配给定字符串中的所有单个字符与elisp?

时间:2013-04-29 17:34:44

标签: regex emacs lisp

例如,我有一个字符串abcdefg. *,如何创建一个可以匹配字符串中每个字符的正则表达式[abcdefg\. *]?问题是字符串中可能存在.等特殊字符。

3 个答案:

答案 0 :(得分:6)

一个简单而强大的解决方案是使用内置的regexp-opt函数,该函数获取固定字符串列表并返回一个有效的正则表达式来匹配其中任何一个。然后,您需要做的就是将原始字符串拆分为单字符段:

(regexp-opt
 (mapcar #'char-to-string
         (string-to-list "abcdefg. *"))) ; => "[ *.a-g]"

答案 1 :(得分:4)

使用regexp-quote功能。

(setq regexp (concat "[" (regexp-quote string) "]"));

请注意,大多数正则表达式字符在方括号内没有特殊含义,因此不需要引用它们。以下是包含字符集中某些特殊字符的Emacs文档:

  

请注意,通常的正则表达式特殊字符在内部并不特殊   一个字符集。一组完全不同的特殊字符   存在于字符集中:']',' - '和'^'。

     

要在字符集中包含']',您必须将其设为第一个   字符。例如,'[] a]'匹配']'或'a'。包括一个   ' - ',写' - '作为集合的第一个或最后一个字符,或者说它   经过一系列的。因此,'[] - ]'匹配']'和' - '。

     

要在一个集合中包含'^',请将它放在任何位置,但是在它的开头   组。 (一开始,它补充了集合 - 见下文。)

答案 2 :(得分:1)

(defun partition (string test &rest more-tests)
  (loop with hash = (make-hash-table)
        for c across string do
        (loop for f in (cons test more-tests)
              for i from 1 do
              (when (funcall f c)
                (setf (gethash i hash) (cons c (gethash i hash)))
                (return))
              finally (setf (gethash 0 hash) (cons c (gethash 0 hash))))
        finally (return (loop for v being the hash-values of hash
                              collect (coerce v 'string)))))

(defun regexp-quote-charclass (input)
  (destructuring-bind (safe dangerous)
      (partition input (lambda (x) (member x '(?\\ ?\] ?^ ?- ?:))))
    (concat "[" (remove-duplicates safe)
            (let ((dangerous (coerce (remove-duplicates dangerous) 'list))
                  (printed safe))
              (with-output-to-string
                (when (member ?\\ dangerous)
                  (setf printed t)
                  (princ "\\\\"))
                (when (member ?: dangerous)
                  (setf printed t)
                  (princ "\\:"))
                (when (member ?\] dangerous)
                  (setf printed t)
                  (princ "\\]"))
                (when (member ?^ dangerous)
                  (if printed (princ "^") (princ "\\^")))
                (when (member ?\- dangerous) (princ "-")))) "]")))

这似乎可以完成这项工作。另外,据我所知,您不需要转义在字符类之外有意义的字符,例如?[?$等。但是,我添加了?:因为在极少数情况下它可能会混淆[:alpha:]之类的东西(你不能通过这个函数获得这个确切的字符串,但我不确定Emacs将如何解析[:组合,所以只是可以肯定。