32

我正在寻找replace-regexp-in-string仅使用文字字符串,没有正则表达式的等价物。

(replace-regexp-in-string "." "bar" "foo.buzz") => "barbarbarbarbarbarbarbar"

但我想要

(replace-in-string "." "bar" "foo.buzz") => "foobarbuzz"

我尝试了各种replace-*功能,但无法弄清楚。

编辑

作为对详尽答案的回报,我决定对它们进行基准测试(是的,我知道所有基准测试都是错误的,但它仍然很有趣)。

的输出benchmark-run(time, # garbage collections, GC time)

(benchmark-run 10000
  (replace-regexp-in-string "." "bar" "foo.buzz"))

  => (0.5530160000000001 7 0.4121459999999999)

(benchmark-run 10000
  (haxe-replace-string "." "bar" "foo.buzz"))

  => (5.301392 68 3.851943000000009)

(benchmark-run 10000
  (replace-string-in-string "." "bar" "foo.buzz"))

  => (1.429293 5 0.29774799999999857)

replace-regexp-in-string 用带引号的正则表达式获胜。临时缓冲区做得非常好。

编辑 2

现在编译!必须进行 10 倍以上的迭代:

(benchmark-run 100000
  (haxe-replace-string "." "bar" "foo.buzz"))

  => (0.8736970000000001 14 0.47306700000000035)

(benchmark-run 100000
  (replace-in-string "." "bar" "foo.buzz"))

  => (1.25983 29 0.9721819999999983)

(benchmark-run 100000
  (replace-string-in-string "." "bar" "foo.buzz"))

  => (11.877136 86 3.1208540000000013)

haxe-replace-string 看起来不错

4

5 回答 5

27

尝试这个:

(defun replace-in-string (what with in)
  (replace-regexp-in-string (regexp-quote what) with in nil 'literal))
于 2013-06-26T16:39:07.633 回答
21

s.el字符串操作库具有s-replace以下功能:

(s-replace "." "bar" "foo.buzz") ;; => "foobarbuzz"

s.el如果您在 Elisp 中使用字符串,我建议从 Emacs 包管理器安装。

于 2014-04-22T11:38:12.883 回答
6

Emacs 28.1(在撰写本文时仍在开发中)将其作为标准提供:

** New function 'string-replace'.
This function works along the line of 'replace-regexp-in-string', but
matching on strings instead of regexps, and does not change the global
match state.
(string-replace FROMSTRING TOSTRING INSTRING)

Replace FROMSTRING with TOSTRING in INSTRING each time it occurs.

(string-replace ".*" "BAR" "foo.*bar.*baz")
 ⇒ "fooBARbarBARbaz"
于 2021-02-04T03:47:03.763 回答
5

我不希望这更快:

(defun haxe-replace-string (string string-a string-b)
  "Because there's no function in eLisp to do this."
  (loop for i from 0 upto
        (- (length string) (length string-a))
        for c = (aref string i)
        with alen = (length string-a)
        with result = nil
        with last = 0
        do (loop for j from i below (+ i alen)
                 do (unless
                        (char-equal
                         (aref string-a (- j i))
                         (aref string j))
                      (return))
                 finally
                 (setq result
                       (cons (substring string last (- j alen)) result)
                       i (1- j) last j))
        finally
        (return
         (if result 
             (mapconcat
              #'identity
              (reverse (cons (substring string last) result)) string-b)
           string))))

因为replace-regexp-in-string是本机功能,但你永远不知道......无论如何,我前段时间出于某种原因写了这个,所以,如果你喜欢比较性能 - 欢迎你尝试:)

另一个想法,使用临时缓冲区:

(defun replace-string-in-string (what with in)
  (with-temp-buffer
    (insert in)
    (beginning-of-buffer)
    (while (search-forward what nil t)
      (replace-match with nil t))
    (buffer-string)))
于 2013-06-26T17:51:14.777 回答
2

s-replace如果您准备好需要它,那很好,但是说您想在加载过程的早期使用字符串中的替换功能并且尚未s.el加载或不需要全部。好吧,这里是s-replacefrom的定义s.el。如您所见,它没有依赖项,因此您可以使用它而无需其余部分s.el

(defun s-replace (old new s)
  "Replaces OLD with NEW in S."
  (declare (pure t) (side-effect-free t))
  (replace-regexp-in-string (regexp-quote old) new s t t))
于 2020-03-03T16:33:50.310 回答