如何用lisp替换文件中的字符串?

如何用lisp替换文件中的字符串?,lisp,replace,Lisp,Replace,用lisp替换文件中的字符串的方法是什么 有一个文件由*文件路径*标识,一个搜索字符串*搜索词*和一个替换字符串*替换词*标识 如何使所有*搜索项*s的实例替换为*替换项*s而生成文件,最好是替换旧文件?可以通过多种方式实现,例如使用正则表达式。我看到的最独立的方式如下所示: (defun replace-in-file (search-term file-path replace-term) (let ((contents (rutil:read-file file-path)))

用lisp替换文件中的字符串的方法是什么

有一个文件由
*文件路径*
标识,一个搜索字符串
*搜索词*
和一个替换字符串
*替换词*
标识


如何使所有
*搜索项*
s的实例替换为
*替换项*
s而生成文件,最好是替换旧文件?

可以通过多种方式实现,例如使用正则表达式。我看到的最独立的方式如下所示:

(defun replace-in-file (search-term file-path replace-term)
  (let ((contents (rutil:read-file file-path)))
    (with-open-file (out file-path :direction :output :if-exists :supersede)
      (do* ((start 0 (+ pos (length search-term)))
            (pos (search search-term contents)
                 (search search-term contents :start2 start)))
           ((null pos) (write-string (subseq contents start) out))
        (format out "~A~A" (subseq contents start pos) replace-term))))
  (values))
请参见
rutil:read file
的实现:


另外请注意,此函数将用任何字符替换搜索词,包括换行符。

在带有ireggex egg的chicken scheme中:

(use irregex) ; irregex, the regular expression library, is one of the
              ; libraries included with CHICKEN.

(define (process-line line re rplc) 
  (irregex-replace/all re line rplc))

(define (quickrep re rplc) 
  (let ((line (read-line)))
    (if (not (eof-object? line))
        (begin 
          (display (process-line line re rplc))
          (newline)
          (quickrep re rplc)))))

(define (main args)
  (quickrep (irregex (car args)) (cadr args)))
编辑:在上面的示例中,缓冲输入不允许regexp跨越 许多行。
为了解决这个问题,这里有一个更简单的实现,它将整个文件扫描为一个字符串:

(use ireggex)
(use utils)

(define (process-line line re rplc) 
  (irregex-replace/all re line rplc))

(define (quickrep re rplc file) 
  (let ((line (read-all file)))
      (display (process-line line re rplc))))

(define (main args)
  (quickrep (irregex (car args)) (cadr args) (caddr args)))

还有一个问题需要解决,但首先警告很少:

  • 要使其在现实生活中真正强大和可用,您需要将其包装到
    处理程序案例中
    ,并处理各种错误,如磁盘空间不足、设备未就绪、读/写权限不足、缓冲区内存分配不足等

  • 这不像替换正则表达式,而是简单的字符串替换。在大文件上进行基于正则表达式的替换可能看起来远不像从一开始看起来那么简单,但值得编写一个单独的程序,如sed或awk或整个语言,如Perl或awk;)

  • 与其他解决方案不同,它将在被替换的文件附近创建一个临时文件,并将迄今为止处理的数据保存到此文件中。这可能会更糟,因为它将使用更多的磁盘空间,但这是更安全的,因为如果程序在中间失败,原始文件将保持完整,超过此,如果再努力,您可以稍后恢复从临时文件替换,例如,您正在将偏移量保存到临时文件中的原始文件中


  • (defun file-replace-string (search-for replace-with file
                                &key (element-type 'base-char)
                                  (temp-suffix ".tmp"))
      (with-open-file (open-stream
                       file
                       :direction :input
                       :if-exists :supersede
                       :element-type element-type)
        (with-open-file (temp-stream
                         (concatenate 'string file temp-suffix)
                         :direction :output
                         :element-type element-type)
          (do ((buffer (make-string (length search-for)))
               (buffer-fill-pointer 0)
               (next-matching-char (aref search-for 0))
               (in-char (read-char open-stream nil :eof)
                        (read-char open-stream nil :eof)))
              ((eql in-char :eof)
               (when (/= 0 buffer-fill-pointer)
                 (dotimes (i buffer-fill-pointer)
                   (write-char (aref buffer i) temp-stream))))
            (if (char= in-char next-matching-char)
                (progn
                  (setf (aref buffer buffer-fill-pointer) in-char
                        buffer-fill-pointer (1+ buffer-fill-pointer))
                  (when (= buffer-fill-pointer (length search-for))
                    (dotimes (i (length replace-with))
                      (write-char (aref replace-with i) temp-stream))
                    (setf buffer-fill-pointer 0)))
                (progn
                  (dotimes (i buffer-fill-pointer)
                    (write-char (aref buffer i) temp-stream))
                  (write-char in-char temp-stream)
                  (setf buffer-fill-pointer 0)))
            (setf next-matching-char (aref search-for buffer-fill-pointer)))))
      (delete-file file)
      (rename-file (concatenate 'string file temp-suffix) file))