You might want to check the Hyperspec's entry on 'open - I think supersede will do what you want, better than overwrite - you'll have to assume the prefixed colons on those keywords, because BBCode thinks overwrite starts with a horrified expression.
Also, Nuntius has an excellent idea, though I'll suggest a slight variation: how about moving the original file to /tmp, then opening its original location for writing, opening the original from /tmp for reading, and stream from one to the other?
Code: Select all
(defun process-file (filepath tempfile string-pattern replacement-string)
(rename-file filepath tempfile)
(with-open-file (outfile filepath :direction :output :if-exists :supersede)
(with-open-file (infile tempfile :direction :input)
(loop for line = (read-line infile nil)
while line do
(format outfile "~a~%" (cl-ppcre:regex-replace string-pattern line replacement-string))))))
The redundant :supersede is an old habit of taking the blunt-instrument approach, and I've left out a bunch of error-handling code for clarity, lack of time and sheer laziness
My approach leaves the original file lying around afterwards which, on one hand is messy, but on the other, means you still have the original if something goes awry during the edit. I'm a sysadmin by profession; it's my job to look surprised when things
don't spontaneously explode into a thousand flaming shards, so I like having a backout plan.
Nuntius' approach, by contrast, is great once you've tested the code and are sure you can rely on it (or re-generate the input) because you don't then have to remember to delete the original file. Much more elegant.