删除lisp程序中的标记

时间:2013-03-06 22:17:31

标签: xml tags lisp

我需要帮助编程。我在Common Lisp中编码,我正在尝试从字符串列表中删除标签。我读了一个XML格式的文件,我的目标是删除<>之间出现的任何文字,如果标记以?xml开头,那么整行需要被删除。我知道命令行上有remove/delete /函数可用,但我试图在我的实际Lisp代码中进行删除,我无法弄清楚如何去做。每次我尝试都会收到错误。

现在这里是我在文件中阅读的代码(可行):

;;;Program: Lisp Assignment 1
;;;Author: Mouse

(defun file-lines (file)
;;;returns a list of strings and the number of
;;;lines read.
    (with-open-file (i file)
    (loop for line = (read-line i nil nil)
          and line-count from 0
          while line
          collect line into lines
          finally (return (values lines line-count)))))

我的想法是,在显示while line的行之后,我将不得不输入代码来检查标记,但我不知道该使用什么。每次我调用removedelete方法时,都会收到错误消息。我不知道我是不是正确地称呼他们。有人可以帮忙吗?

1 个答案:

答案 0 :(得分:1)

我认为你的问题不是很清楚。为什么要询问从字符串列表中删除标记,而示例代码从文件中读取行?假设你真的在问一个字符串列表,那么标签可能会分布在多个字符串上吗?此外,您询问的是removedelete,但未提及您的确尝试过以及失败的原因。如果你想直接改变文件的内容,那么你不能只从流中删除东西并期望它能够工作。

这是一种通过逐字符读取流来删除标记的简单方法:

(defun remove-tags (string)
  (flet ((read-tag (instream)
           (loop for char = (read-char instream nil nil)
                 while (not (string= char #\>)))))
    (with-output-to-string (outstream)
      (with-input-from-string (instream string)
        (loop for char = (read-char instream nil nil)
              while char
              if (char= char #\<) do (read-tag instream)
              else do (write-char char outstream))))))


CL-USER> (remove-tags "<p><a href=\"foo\">bar</a> frob <emph>baz</emph> quux</p>")
"bar frob baz quux"

如果您想要读取和写入文件,只需将with-output-to-stringwith-input-from-string替换为相应的with-open-file表单。

但这只是一个让你入门的例子。即使这只是一个学术练习,你需要使它更加健壮。例如,它失败了:

CL-USER> (remove-tags "<p><a href=\"fo>o\">bar</a>")
"o\">bar"

(如果我没记错的话,XML字符串中允许使用未转义的结束尖括号。)

此外,这既没有经过测试也没有针对速度进行优化 - 处理字符可能太慢,并且它不处理?xml标记的删除。所有这些都留给读者练习。

对于实际目的,您可能真的只使用其中一个XML库,或者使用regexen并祈祷。解析和处理XML是一个问题,已经在许多库中以实际使用的几乎所有语言解决了,并且有很多细节可能出错(如果你真的只是想删除一些标签,那可能不是,但是 principiis obsta ),无论如何它都是一项相当无聊的练习。