2009-07-14 81 views
5

我今天得到了这条奇怪的代码行,它告诉我'空'或'不空',具体取决于CWD是否有任何项目(...除外)。这个Perl是如何检查一个目录是否为空的工作?

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

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

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

+0

随意编辑更合适的标签 – dsm 2009-07-14 15:39:26

+3

哈哈,你真是太好笑了!我在地板上大笑起来。你叫Perl线噪声!!!! HAHAHAHAHAHAHAHAHAHAHAHAHA! – jrockway 2009-07-14 15:50:45

+0

好提交'年度混淆'。我喜欢Perl,但我更喜欢Perl代码中的注释。 – Boldewyn 2009-07-14 15:53:24

回答

16

这是一个高尔夫球单线。 -e标志意味着执行命令行的其余部分作为程序。 -l支持自动行结束处理。

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

该部分

(q=not =) 

是包含单一值的列表 - 字符串 “不”。 q=...=是一个可替换的字符串分隔符,显然是因为单引号用于引用单行。

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

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

有很多发生在这里。比较测试glob是否返回了完全两个项目的列表(假设为...),但它是如何很棘手的。内部圆括号表示一个空列表。分配到此列表将glob放入列表上下文中,以便它返回目录中的所有文件。 (在标量上下文中,它将表现得像一个迭代器,一次只返回一个)。赋值本身在标量上下文中进行评估(位于比较的右侧),因此会返回分配的元素数量。

领先的+是为了防止Perl解析列表作为参数到print。尾部.empty将字符串“empty”连接到列表中的任何字符串(即“not  ”或空字符串)。

3

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

7
<.* *> 

是由两个模式的水珠:.*是与.开始,*对应于所有文件的所有文件名(这比通常的DOS/Windows约定不同)。

(()=<.* *>) 

评估列表上下文中的glob,返回所有匹配的文件名。

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

0

该功能的文档是here。 (滚动临近节结束)

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')); 

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