2

我必须处理某些可能包含转义字符的文件,例如vertical-tab(又名“^k”),这确实与REPL(SBCL)和一些库(例如cxml-stp)混淆。

是否有涵盖 CL 中这些字符的参考,我该如何过滤它们?我刚刚找到了一些emacs-lisp 参考资料,但据我所知,这些资料肯定对普通 lisp 不起作用。

4

3 回答 3

2
(defun sanitize (string)
  (remove-if
   #'(lambda (x)
       (and (< x 32)
            (not (or (= x 13) (= x 10)))))
   string))

(with-output-to-string (s)
    (let ((sanitized 
          (sanitize
           (do ((a (make-array 100 :element-type '(unsigned-byte 8)))
                (i 0 (1+ i)))
               (nil)
             (when (= i (length a))
               (return a))
             (setf (aref a i) (random 64))))))
      (dotimes (i (length sanitized))
        (princ (code-char (aref sanitized i)) s))))

但这可能取决于您的来源/您想要包含哪些字符。这适用于 ASCII - 如果您保证它们采用 (mod 128) 格式。Unicode 是一个复杂得多的问题。但是,这仍然会过滤掉可能在 shell 脚本中具有特殊含义的字符,但这对于以 UTF-8 等格式构建 Unicode 字符串不是一个好主意,因为如果您的源以字节形式出现,您将需要解析它并确保它们形成有效的 UTF-whatever 格式。您还需要注意 Unicode 中可能的替代(冗余)表示,由变音符号与字母组合形成的对。代码点范围内的空白区域等等......

说实话,我还没有见过 100% 符合 Unicode 实现的 Lisp。它比听起来更难,而且你可能只需要它的一个子集。

如果您想要实际案例,而这对 Unicode 字符串来说不是一个好主意 - 谷歌搜索“目录攻击”和 IIS5 漏洞。

于 2012-06-22T23:59:00.840 回答
1

具有合适测试功能的 REMOVE-IF 应该可以解决问题。

于 2012-06-22T16:22:14.737 回答
1

正如您所注意到的,使用 REMOVE-IF 的问题在于,您正在寻找的角色没有一个很好的句柄。在 Hyperspec 中搜索“半标准字符”,您会看到命名空白字符列表非常短—— #\Newline, #\Space, #\Tab, #\Return, #\Page, #\Rubout, #\Backspace

如果您使用 Emacs 作为您的编辑器,那么找到目标值、剪切它并将其作为文字粘贴到您的代码中并不难——但这也不是一个好主意。另一方面,如果你能找到字符并将其粘贴到你的 REPL 中,那么你应该能够找到一种调用(char-name)它的方法,ala: (char-name (aref "<copy-paste-char>" 0))

I'd do something like what wvxvw is doing, except more exploratory. Write code to walk over your file, collect all characters in use, print their codes and their names. (Don't just print every one; count the number of occurrences using a hashtable, i.e. (incf (gethash <char> ht 0)), so that you can get a sense for how frequently things occur, and you're not overwhelmed with output.) Then you can make a more informed decision on how to identify & eliminate characters you don't want in your file.

于 2012-06-23T21:42:02.493 回答