5

我今天得到了这行奇怪的代码,它告诉我“空”或“非空”,具体取决于 CWD 中是否有任何项目(除了.and ..)。

我想知道它是如何工作的,因为它对我来说毫无意义。

perl -le 'print+(q=not =)[2==(()=<.* *>)].empty'

我感兴趣的一点是<.* *>。我不明白它如何获取目录中所有文件的名称。

4

5 回答 5

16

这是一个打高尔夫球的单线。该-e标志表示将命令行的其余部分作为程序执行。-l启用自动线端处理。

<.* *>部分是一个包含两个要扩展的模式的 glob:.**.

这部分

(q=not =)

是一个包含单个值的列表——字符串“not”。这q=...=是一个备用字符串分隔符,显然是因为单引号被用来引用单行。

[...]部分是该列表的下标。取决于此比较的结果,下标的值将是 0(值“not”)或 1(无,打印为空字符串):

2 == (()=<.* *>)

这里发生了很多事情。比较测试 glob 是否返回了正好两个项目的列表(假设是.and ..),但它是如何做到的却很棘手。内括号表示一个空列表。分配给此列表会将 glob 置于列表上下文中,以便它返回目录中的所有文件。(在标量上下文中,它的行为类似于迭代器,一次只返回一个。)赋值本身在标量上下文中进行评估(在比较的右侧),因此返回分配的元素数。

引导+是防止 Perl 将列表解析为print. 尾部.empty将字符串“empty”连接到列表中的任何内容(即“not”或空字符串)。

于 2009-07-14T15:55:26.907 回答
7
<.* *>

是一个由两种模式组成的 glob:.*都是以所有文件开头.*对应于所有文件的文件名(这与通常的 DOS/Windows 约定不同)。

(()=<.* *>)

在列表上下文中计算 glob,返回所有匹配的文件名。

然后,比较2将其放入标量上下文中,因此将其2与返回的文件数进行比较。如果该数字是2,那么唯一的目录条目是...,句点。;-)

于 2009-07-14T15:48:48.387 回答
3

<.* *>意味着(glob(".*"), glob("*"))glob以与 shell 相同的方式扩展文件模式。

于 2009-07-14T15:47:12.477 回答
2

我发现该B::Deparse模块在破译一些让大多数程序员眼花缭乱的东西方面有很大帮助,例如q=...=结构:

$ perl -MO=Deparse,-p,-q,-sC 2>/dev/null << EOF
> print+(q=not =)[2==(()=<.* *>)].empty
> EOF
use File::Glob ();
print((('not ')[(2 == (() = glob('.* *')))] . 'empty'));

当然,这不会立即产生“可读”的代码,但它肯定会转换一些绊脚石。

于 2009-07-14T16:07:25.103 回答
0

该功能的文档在此处。(滚动到该部分的末尾附近)

于 2009-07-14T16:01:07.130 回答