【发布时间】:2015-07-23 01:23:24
【问题描述】:
我正在尝试编写 Python 正则表达式搜索和替换的 Common Lisp 版本,并对文件进行就地修改:
import fileinput, re
for line in fileinput.input(inplace=1, backup='.bak'):
line = re.sub(r"foo", "bar", line, re.M)
print (line)
这是我能想到的 Common Lisp 代码:
(require :cl-ppcre)
(defun in-place-subst (file)
(with-open-file (stream file :direction :io :if-exists :overwrite)
(loop for line = (read-line stream nil)
while line do
(write-line (cl-ppcre:regex-replace-all "foo" line "bar") stream))))
它确实有效。现在替换文本将附加在文件的末尾。我的直接问题是我不知道如何替换内容。
为了更好地解释,如果file.txt 包含:
1 foo
2 bar
3 foobar
调用后
(in-place-subst "file.txt")
我明白了:
1 foo
2 bar
3 foobar
1 bar
2 bar
3 barbar
而不是正确的替换:
1 bar
2 bar
3 barbar
我尝试了所有可能的with-open-file 选项(来自Successful Lisp),但没有成功:
Keyword Value Action if File Exists
---------- ------------------ ---------------------------------------
:IF-EXISTS NIL return NIL
:IF-EXISTS :ERROR signal an error
:IF-EXISTS :NEW-VERSION next version (or error)
:IF-EXISTS :RENAME rename existing, create new
:IF-EXISTS :SUPERSEDE replace file upon CLOSE
:IF-EXISTS :RENAME-AND-DELETE rename and delete existing, create new
:IF-EXISTS :OVERWRITE reuse existing file (position at start)
:IF-EXISTS :APPEND reuse existing file (position at end)
有人可以向我发送正确的方向,以便该函数以正确的方式呈现file.txt吗?
另外,如果cl-ppcre 是可用的,Common Lisp 惯用 方法是什么?
有没有更简洁的方法来使用 Common Lisp 进行就地正则表达式替换?
【问题讨论】:
-
FILE-POSITION读取并设置文件位置。您可能想尝试一下。 -
感谢您的建议。我试过
(file-position stream :start),试图重置流的文件位置,但没有太大进展。我确信可以用更多的代码来做到这一点,(也许在内存中制作副本,进行替换并回写),但我希望找到一种更简洁,或许更惯用的方式。 -
保存文件位置。阅读该行。将文件位置重置为开头。写新行。请注意,它不会更改行的大小或扩展文件。如果您的替换时间更短或更长,那么您需要处理...
-
谢谢,您的评论让我思考了很多,并帮助我了解了更多文件位置的细微差别。我想到,更简单的方法是首先写入临时文件(如 Renzo 的回答),特别是因为在使用无法提前知道长度的正则表达式时来回控制文件位置变得不平凡。不过,你的想法很有趣,也是一个很好的练习。我需要花更多的时间在上面。我觉得可能有比临时文件技术更“lisp-esque”的方式。非常感谢。
-
@RainerJoswig 我花了几个小时试图通过使用
FILE-POSITION读取和设置文件位置来使该功能正常工作。正如您所说,问题在于与原件长度不同的替换。我几乎让它工作,但我需要截断流。似乎这样的功能还不可能,除非有人使用 Franz:franz.com/support/documentation/current/doc/… 我还找到了一个建议:mail-archive.com/cdr-discuss@common-lisp.net/msg00044.html 你知道现在有什么图书馆提供这个吗?
标签: file-io lisp common-lisp idioms in-place