2

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

4

3 回答 3

6

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

(regexp-opt
 (mapcar #'char-to-string
         (string-to-list "abcdefg. *"))) ; => "[ *.a-g]"
于 2013-04-29T19:49:03.093 回答
4

使用该regexp-quote功能。

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

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

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

要在字符集中包含 ']',您必须使其成为第一个字符。例如,'[]a]' 匹配 ']' 或 'a'。要包含“-”,请将“-”写为集合的第一个或最后一个字符,或将其放在范围之后。因此,'[]-]' 匹配 ']' 和 '-'。

要在集合中包含“^”,请将其放在集合开头以外的任何位置。(一开始,它是对集合的补充——见下文。)

于 2013-04-29T17:38:04.863 回答
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 "-")))) "]")))

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

于 2013-04-29T19:26:36.960 回答