Lisp 什么是SBCL';macOS、Linux、FreeBSD上的s路径名通配符约定?
今天在Mac上试用Lisp时,我发现以下内容有点迷失方向:Lisp 什么是SBCL';macOS、Linux、FreeBSD上的s路径名通配符约定?,lisp,common-lisp,sbcl,Lisp,Common Lisp,Sbcl,今天在Mac上试用Lisp时,我发现以下内容有点迷失方向: $ sbcl This is SBCL 1.4.14, an implementation of ANSI Common Lisp. More information about SBCL is available at <http://www.sbcl.org/>. SBCL is free software, provided as is, with absolutely no warranty. It is most
$ sbcl
This is SBCL 1.4.14, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
* (directory "*")
NIL
* (directory "*.*")
(#P"/private/tmp/sbcl/quicklisp.lisp" #P"/private/tmp/sbcl/test1.lisp"
#P"/private/tmp/sbcl/test2.lisp")
$sbcl
这是SBCL 1.4.14,是ANSI Common Lisp的一个实现。
有关SBCL的更多信息,请访问。
SBCL是免费软件,按原样提供,绝对没有保修。
它主要是在公共领域;某些部分在以下章节中提供:
BSD风格的许可证。请参阅中的学分和复制文件
分发以获取更多信息。
*(目录“*”)
无
*(目录“***”)
(#P)/private/tmp/sbcl/quicklisp.lisp“#P)/private/tmp/sbcl/test1.lisp”
#P“/private/tmp/sbcl/test2.lisp”)
在macOS、Linux、FreeBSD上,*
表示所有文件,这可能是大多数其他UNIX所喜欢的。我只见过在DOS和Windows上使用的*.
根据,通配符取决于实现。那么,SBCL在上述操作系统上使用的约定到底是什么呢?我怎么才能知道呢?没有描述这一点。即使在上述三个操作系统之间也会有所不同吗?
它说“但无论如何,这可能不是我们目前所做的”,但我不确定这是否意味着这条评论可能对当前版本或其他内容不准确。我假设至少通配符部分是正确的
这里重要的一点是,目录、文件和类型组件都是单独考虑的,因此必须为文件名和扩展名(又称类型组件)使用单独的通配符,并用点分隔它们
注释中称这些为“Unix名称字符串”,但我认为这适用于所有平台。以下方法可行,我认为应该适用于大多数实现(我在MacOS上的LW、Linux上的SBCL和MacOS上的Clojure上都试过) 然后,例如
(directory(wild directory)/tmp/”)
将返回/tmp/
目录中的所有内容,(directory(wild directory(user homedir pathname)))
将返回主目录中的所有内容
但是请注意(这显然是非常依赖于实现的,但看起来我使用的所有实现都同意这一点,我也同意他们的解释):(directory(wild directory)/tmp”)
将返回/
中的所有内容,因为“/tmp”
作为路径名意味着“名为/
的目录中名为tmp
的文件”。正如我所说,我认为这是一个合理的解释:引用目录的路径名以/
结尾
还要注意的是,+wild file+
确实是wild:它不会以任何特殊方式处理名称以
开头的文件。我认为应该如何解析像/foo/bar/.x
这样的文件名存在相当明显的模糊性,尽管我尝试过的三种实现都采用了我认为正确的解释:名称是“.x”
,类型是nil
(/foo/bar/.x.y
似乎是用“y”类型解析的
我认为这也是合理的)
在任何情况下,如果您需要执行任何严重的路径名操作,技巧是定义一组包装函数和常量,然后使用它们,并在它们后面隐藏实现依赖性(在本例中,实现依赖于如何获取目录中的所有文件,其他所有内容在实现之间似乎都是通用的)
我怀疑存在这样一个抽象层,但不幸的是,我不知道它是什么
写了这篇文章之后,我尝试了CLISP,它做了一些有趣的不同:看起来
目录
不返回子目录名,只返回文件名。我认为这是一个非常合理的实现,但它需要更多的抽象。尝试(描述#p“*”)
,即显示如何根据目录、名称等解析路径名。路径名是一个复杂的问题,不可避免地在某种程度上依赖于实现。CL有一个非常复杂的路径名系统,它比通常假设的更具可移植性,尽管它存在路径名具有类型(ie扩展)的问题而在Unixoid系统上,扩展只是一种约定。您可能想看看解析本机名称字符串
的作用:特别是(路径名类型(解析名称字符串“*”))
&它与(路径名类型(解析本机名称字符串“*”)相比如何
。可能重复请参见:@tfb您对这些命令的期望是什么?ECL和SBCL都返回NIL。
;;; FIXME: the below shouldn't really be here, but in documentation
;;; (chapter 19 makes a lot of requirements for documenting
;;; implementation-dependent decisions), but anyway it's probably not
;;; what we currently do.
;;;
;;; Unix namestrings have the following format:
;;;
;;; namestring := [ directory ] [ file [ type [ version ]]]
;;; directory := [ "/" ] { file "/" }*
;;; file := [^/]*
;;; type := "." [^/.]*
;;; version := "." ([0-9]+ | "*")
;;;
;;; Note: this grammar is ambiguous. The string foo.bar.5 can be
;;; parsed as either just the file specified or as specifying the
;;; file, type, and version. Therefore, we use the following rules
;;; when confronted with an ambiguous file.type.version string:
;;;
;;; - If the first character is a dot, it's part of the file. It is not
;;; considered a dot in the following rules.
;;;
;;; - Otherwise, the last dot separates the file and the type.
;;;
;;; Wildcard characters:
;;;
;;; If the directory, file, type components contain any of the
;;; following characters, it is considered part of a wildcard pattern
;;; and has the following meaning.
;;;
;;; ? - matches any one character
;;; * - matches any zero or more characters.
;;; [abc] - matches any of a, b, or c.
;;; {str1,str2,...,strn} - matches any of str1, str2, ..., or strn.
;;; (FIXME: no it doesn't)
;;;
;;; Any of these special characters can be preceded by an escape
;;; character to cause it to be treated as a regular character.
(defun directory-pathname (p)
;; Everything but the file part: this should be called
;; non-file-pathname or something
(make-pathname :name nil :type nil :version nil
:defaults (pathname p)))
(defconstant +wild-file+
;; a completely wildcarded filename with no other components
(make-pathname :name ':wild
:type ':wild
:version ':wild))
(defun wild-directory (d)
;; Take the directory parts of D and return a pathname which matches
;; all files in tat directory.
;;
;; Actually we could just use D for the defaults since it's only
;; used for defaults and that's less consy, but never mind
(merge-pathnames +wild-file+ (directory-pathname d)))