【问题标题】:How do I assign an element of @ARGV to a $variable, then print it?如何将@ARGV 的元素分配给$ 变量,然后打印它?
【发布时间】:2021-02-14 14:01:12
【问题描述】:

这个问题经常以各种方式被问到,但是我要再问一次,因为我没有完全理解@ARGV的应用,因为我还没有找到这个问题的答案(或者,更有可能是我不明白已经提供的答案和解决方案)。

问题是,为什么命令行没有读取任何内容?另外,如何解密错误信息,

在连接 (.) 或字符串 ... 中使用未初始化的值 $name?

我了解@ARGV 是一个存储命令行参数(文件)的数组。我也明白它可以像任何其他数组一样被操作(记住索引$ARGV[0] 与文件名变量的命令行功能$0 不同)。我知道在while循环中,菱形运算符会自动将shift 的第一个元素@ARGV 作为$ARGV[ ],在输入处读取一行。

我不明白的是如何将@ARGV 的元素分配给标量变量,然后打印数据。例如(取自Learning Perl的代码概念),

my $name = shift @ARGV;

while (<>) {
    print “The input was $name found at the start of $_\n”;
    exit;
}

就代码而言,$name 的输出是空白的;如果我省略shift()$name 将输出0,因为我相信它应该在标量上下文中,但它没有回答为什么命令行输入也不被接受的问题。我们将不胜感激您的见解。

谢谢。

【问题讨论】:

  • 如果这是您的整个程序(以use warnings;use strict; 开头)然后当您运行它时带有参数,例如prog.pl hello,它将等待输入,因为&lt;&gt; 读取STDIN 如果没有文件给程序。 (因为你 shift-ed 来自 @ARGV,它只有 hello 字,所以里面什么都没有,所以 &lt;&gt; 等待。)然后你按下回车键,它运行 print 语句,hello 在变量$name。 (如果你在开始时什么都不给程序,那么$name 是空的,但你似乎知道这一点。)我不明白它为什么/如何对你有不同的表现?
  • 在循环中while (&lt;&gt;) 从终端读取的任何输入都分配给$_ - 你不打印它,所以没有办法看到它。但是,这仍然不能解释如何让 $name 为空(如果在启动程序时将参数传递给程序)。所以你的问题描述有问题?请注意,@ARGV 中的内容被&lt;&gt; 视为文件名,这些文件将逐行打开和读取。
  • perlvar 页面中查找 Perl 的特殊变量。在perldiag 页面中查找错误消息的简要说明。
  • 太好了,所以很清楚,尤其是 ikegami 的回答:)。这是一个很好的问题,写得很仔细。请注意,我上面提到的,如果您向脚本提供参数,那么当执行到 &lt;&gt; 时,这些参数将被视为文件(除非它们已经从 @ARGV 之前被删除),它们被打开并逐行读取线。这非常有用,因为您可以使用while (&lt;&gt;)或者逐行处理STDIN(提示并等待输入,或将输入“通过管道”读入程序) 处理文件。灵活:)

标签: perl command-line-arguments argv string-interpolation


【解决方案1】:

my $name = shift @ARGV; 确实分配了程序的第一个参数。如果你得到Use of uninitialised value $name in concatenation (.) or string at ...,那是因为你没有为你的程序提供任何参数。

$ perl -we'my $name = shift(@ARGV); print "My name is $name.\n"'
Use of uninitialized value $name in concatenation (.) or string at -e line 1.
My name is .

$ perl -we'my $name = shift(@ARGV); print "My name is $name.\n"' ikegami
My name is ikegami.

之后使用&lt;&gt;绝对没有问题。

$ cat foo
foo1
foo2

$ cat bar
bar1
bar2

$ perl -we'
   print "(\@ARGV is now @ARGV)\n";
   my $prefix = shift(@ARGV);

   print "(\@ARGV is now @ARGV)\n";
   while (<>) {
      print "$prefix$_";
      print "(\@ARGV is now @ARGV)\n";
   }
' '>>>' foo bar
(@ARGV is now >>> foo bar)
(@ARGV is now foo bar)
>>>foo1
(@ARGV is now bar)
>>>foo2
(@ARGV is now bar)
>>>bar1
(@ARGV is now )
>>>bar2
(@ARGV is now )

【讨论】:

  • 感谢您详细说明脚本的正确性以及我没有按照脚本所期望的那样在命令行中提供输入的疏忽。我不熟悉您从命令行编写和运行脚本的方法,但我会阅读您的示例。
  • 三个尖括号&gt;&gt;&gt;是干什么用的?
  • 我在命令行上提供程序的事实是无关紧要的。如果程序在文件中,也会发生同样的情况。所以只是假装perl -we'...'perl foo.pl./foo.pl /// 这就是论点。使用名称没有任何意义
  • @Den 当您从命令行运行 perl -e'...' 时,'' 之间的内容被视为 Perl 程序并被执行(即 -e)。方便快速测试(或者甚至可能用完 bash 脚本等)。此外,还有许多方便的开关,例如perl -ne'...' file 将打开file 并逐行应用'' 中的代码(即-n)。见perlrun。在 bash shell 中,您甚至可以将其分布在多行中,因此可以将上面的程序复制并粘贴到您的 shell 中,然后按回车键运行它。
  • @Den 我听说过,没见过。很抱歉一开始的坎坷——任何编程语言都可能让你不知所措,特别是 Perl 是一种强大的工具。但是关于它的一个好处是,“轻松地”(相对)学习基础知识应该是可行的,所以也许那本书在这个主题上做得不好?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 2015-01-13
  • 1970-01-01
  • 2020-05-28
  • 2012-01-05
  • 1970-01-01
相关资源
最近更新 更多