检查目录是否为空的 Perl 一个衬垫是如何工作的?

发布于 2024-07-27 15:48:32 字数 275 浏览 2 评论 0原文

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

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

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

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

I got this strange line of code today, it tells me 'empty' or 'not empty' depending on whether the CWD has any items (other than . and ..) in it.

I want to know how it works because it makes no sense to me.

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

The bit I am interested in is <.* *>. I don't understand how it gets the names of all the files in the directory.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

佞臣 2024-08-03 15:48:33

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

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

这部分

(q=not =)

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

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

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

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

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

It's a golfed one-liner. The -e flag means to execute the rest of the command line as the program. The -l enables automatic line-end processing.

The <.* *> portion is a glob containing two patterns to expand: .* and *.

This portion

(q=not =)

is a list containing a single value -- the string "not". The q=...= is an alternate string delimiter, apparently used because the single-quote is being used to quote the one-liner.

The [...] portion is the subscript into that list. The value of the subscript will be either 0 (the value "not ") or 1 (nothing, which prints as the empty string) depending on the result of this comparison:

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

There's a lot happening here. The comparison tests whether or not the glob returned a list of exactly two items (assumed to be . and ..) but how it does that is tricky. The inner parentheses denote an empty list. Assigning to this list puts the glob in list context so that it returns all the files in the directory. (In scalar context it would behave like an iterator and return only one at a time.) The assignment itself is evaluated in scalar context (being on the right hand side of the comparison) and therefore returns the number of elements assigned.

The leading + is to prevent Perl from parsing the list as arguments to print. The trailing .empty concatenates the string "empty" to whatever came out of the list (i.e. either "not " or the empty string).

长不大的小祸害 2024-08-03 15:48:33
<.* *>

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

(()=<.* *>)

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

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

<.* *>

is a glob consisting of two patterns: .* are all file names that start with . and * corresponds to all files (this is different than the usual DOS/Windows conventions).

(()=<.* *>)

evaluates the glob in list context, returning all the file names that match.

Then, the comparison with 2 puts it into scalar context so 2 is compared to the number of files returned. If that number is 2, then the only directory entries are . and .., period. ;-)

孤蝉 2024-08-03 15:48:33

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

<.* *> means (glob(".*"), glob("*")). glob expands file patterns the same way the shell does.

凉世弥音 2024-08-03 15:48:33

我发现 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'));

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

I find that the B::Deparse module helps quite a bit in deciphering some stuff that throws off most programmers' eyes, such as the q=...= construct:

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

Of course, this doesn't instantly produce "readable" code, but it surely converts some of the stumbling blocks.

不可一世的女人 2024-08-03 15:48:33

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

The documentation for that feature is here. (Scroll near the end of the section)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文