glob @argv上的perl优先级

时间:2012-06-07 13:01:27

标签: windows perl glob operator-precedence

由于在Windows * .csv上没有从命令行扩展到@ARGV,我通常最终会做类似的事情

map { glob } @ARGV获取文件名。

然而,我遇到了一个异常,只是想了解真正发生的事情。我刚读完“奇怪的土地上的陌生人”,所以我可以说我没有完全理解!

use Modern::Perl;

# gets the filelist but then warns
say "Test 1 ", '-' x 20;
do { func($_) for map { glob } @ARGV } or warn "at least one arg expected\n";
say '-' x 27, "\n";

# works ok
say "Test 2 ", '-' x 20;
my @x = map { glob } @ARGV or warn "at least one arg expected\n";
func($_) for @x;
say '-' x 27, "\n";

# prints 2 (there are two files)
say "Test 3 ", '-' x 20;
func($_) for (map { glob } @ARGV or warn "at least one arg expected\n");
say '-' x 27, "\n";

sub func { 
  say "in func = $_[0]";
}

输出:

Test 1 --------------------
in func = t.csv
in func = t2.csv
at least one arg expected
---------------------------

Test 2 --------------------
in func = t.csv
in func = t2.csv
---------------------------

Test 3 --------------------
in func = 2
---------------------------

测试1:我不明白为什么do没有真正返回,func返回最后一个say语句,返回true如果输出了什么。或者for是否用作do的回复?

测试3:显然隐含了一个标量上下文,但是如何?我在地图周围使用括号?

谢谢, 理查德。

2 个答案:

答案 0 :(得分:3)

测试1

由于for语句修饰符,第一种情况是评估false(您可能认为它是无效的)。观察:

  DB<1> x do { func($_) for map { glob } @ARGV }
in func = t.csv
in func = t2.csv
0  ''
  DB<2> x do { func 't.csv' ; func 't2.csv' }
in func = t.csv
in func = t2.csv
0  1

请注意,它是语句修饰符,而不是表达式修饰符。在进行这种区分的语言中,表达式具有返回值,但不具有语句。

Perl就是这样一种语言。鉴于简单的程序

#! perl
@a = (1 for 6, 7, 8);

尝试运行它会因语法错误而失败。

syntax error at foo line 2, near "1 for "
Execution of foo aborted due to compilation errors.

您可以更直接地在第一次测试中表达您的意图

map func($_), map glob, @ARGV or warn "at least one arg expected\n";

给出预期的输出。

Test 1 --------------------
in func = t.csv
in func = t2.csv
---------------------------

测试3

在第三种情况下,您会得到标量上下文,因为这是Perl’s logical-or定义为工作的方式。

  

C风格的逻辑或

     

二进制||执行短路逻辑OR运算。也就是说,如果左操作数为true,则甚至不评估右操作数。标量或列表上下文如果被计算,则向下传播到右操作数。

左操作数总是在二进制(标量)上下文中计算。整个表达式的上下文仅归于右操作数。

答案 1 :(得分:2)

保持简单,并发布可操作的便携式解决方案。


测试1

您正在查看do的结果。

这是for的结果,do评估的最后一项操作,for没有返回任何有用的内容。


测试2

您正在检查列表分配的结果。

标量上下文中的列表赋值评估其右侧(map)返回的标量数。


测试3

您正在迭代or返回的值。

or返回其LHS(在标量上下文中评估)或其RHS。这将是由标量上下文(数字)中评估的map返回的值或warn返回的值(布尔值)。


您希望操作系统同时返回列表和数字。这不起作用。

请注意,您需要bsd_glob,否则带有空格的路径会被破坏。 (glob实际上使用了bsd_glob的内容!)

use File::Glob qw( bsd_glob );
@ARGV = map bsd_glob($_), @ARGV if $^O eq 'MSWin32';
die if @ARGV < 2;
func($_) for @ARGV;