如何替换给定字符串中的任何转义字符(例如垂直制表符)

时间:2012-06-22 14:53:50

标签: escaping common-lisp

我必须处理可能包含诸如vertical-tab(又名“^ k”)之类的转义字符的某些文件,这会使REPL(SBCL)和某些库(例如cxml-stp)混乱。

是否有一个参考文献涵盖CL中的这些字符,我该如何过滤它们?我刚刚发现了一些emacs-lisp reference,但大多数情况下,就我能够确认而言,这些并不适用于普通的lisp。

3 个答案:

答案 0 :(得分: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-任何格式。您还需要处理Unicode中可能的替代(冗余)表示,由变音符号与字母组合形成的对。代码点范围内的空白区域等等......

说实话,我还没有看到一个具有100%符合Unicode实现的Lisp。它比听起来更难,你可能只需要它的一部分。

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

除了更多的探索之外,我会做类似wvxvw正在做的事情。编写代码以遍历您的文件,收集正在使用的所有字符,打印其代码及其名称。 (不要只打印每一个;使用哈希表计算出现次数,即(incf (gethash <char> ht 0)),以便您可以了解事情发生的频率,并且您不会被输出所淹没。)然后你可以就如何识别和识别做出更明智的决定消除文件中不需要的字符。