涉及-s switch
(例如https://stackoverflow.com/a/29613573/14557599)的堆栈溢出的示例给予--
的位置,如下所示:
perl -s -e 'if ($xyz) { print "$xyz\n" }' -- -xyz
perldoc perlrun
:
-s enables rudimentary switch parsing for switches on the command line
after the program name but before any filename arguments (or before
an argument of --). Any switch found there is removed from @ARGV
and sets the corresponding variable in the Perl program. The
following program prints "1" if the program is invoked with a -xyz
switch, and "abc" if it is invoked with -xyz=abc.
#!/usr/bin/perl -s
if ($xyz) { print "$xyz\n" }
我对“before an argument of --"感到困惑,因为上面的例子是有效的,-xyz是在--
之后。如果像文档中写的那样写:
perl -xyz -- -s -e 'if ($xyz) { print "$xyz\n" }'
Can't open perl script "-s": No such file or directory
根据我对它的理解,我想在doc中写:
在程序名之后(或参数--之后),但在任何文件名参数之前
我找的钱对吗?也许在此之前的某个时候,perlrun的语法确实如文档中所描述的那样,但后来被更改,但文档被更新以反映这一点?
- 编辑二:*
在阅读了所有的答案之后:
在程序名之后(或者如果程序是通过-e或-E开关指定的,则在--参数第一次出现之后),但在任何文件名参数之前(或者在--之前,如果程序名是第一次出现,如果程序是通过-e或-E开关指定的,则在第二次出现)
- TL;DR*
编辑:
为了回应zdin的回答(注意:我没有找到option
,switch
的定义;似乎它们是同义词,两者都被用作bash命令行参数和perl程序中的shebang行参数)。
echo a-a-a > 1.txt
q.pl
#!/usr/bin/perl -sp
s/a/b/;
if ($xyz) { print "$xyz\n" }
w.pl
#!/usr/bin/perl -s
s/a/b/;
if ($xyz) { print "$xyz\n" }
我可以调用 *.pl,传递1.txt作为参数w/out --
:
./q.pl -xyz=a 1.txt
a
b-a-a
perl -p ./q.pl -xyz=a 1.txt
a
b-a-a
单行线:
perl -spe 's/a/b/;if ($xyz) { print "$xyz\n" }' -- -xyz=a 1.txt
a
b-a-a
这表明我的重新表述对于通过程序名和一行程序运行都是有效的。
P.S.
perl --version
This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-linux-gnu-thread-multi
3条答案
按热度按时间h7wcgrx31#
perldoc中引用的语句是正确的,如果不完整的话,因为它没有提到一行程序的不同行为。混淆源于存在
-s
的选项解析的特殊性。该特定语句指的是运行文件中的程序,如图所示。
我们能做
标记选项(“开关”)的结束,之后是参数(对于
@ARGV
)。如果以下参数中的第一个看起来像选项(以-
开头),则需要此标记;或者我们可以忽略--
(如果第一个参数不是以-
开头),或者如果没有参数被传递这些打印
X
。(或者perl -s test_s_switch.pl ...
w/o shebang行上的-s
。)但是对于命令行程序(“一行程序”),它会按照您观察到的方式运行
我们得到
X
打印。这里--
是必要的,以指示选项的结束,以便在它之后进入参数。这种区别在perlrun中的命令开关开始时说明--
表示选项结束并禁止进一步的选项处理。--
之后的任何参数都被视为文件名和参数。这种差异的原因是,在文件中给出的程序的选项(“开关”)必须在程序文件名之前,留下
-tt=X
的位置(-s
的参数)紧跟在程序文件名之后,在--
或参数之前。但是使用命令行程序(“一行程序”)程序本身是选项/开关的一部分(-e'...'
)所以其他选项可能会跟随,所以要传递-s
(-tt=X
)的参数,我们必须先有--
,以指示选项的结束。使用一行程序,在不使用
--
的情况下尝试将-tt=X
转换为交换机(t
、t
和=X
)并导致
因为
-t
是合法的交换机,并且重复它(-tt
)被接受。在这一点上,我必须注意
perlrun
中-s开关描述末尾的一条注解...
由于这些原因,不鼓励使用
-s
。请参阅Getopt::Long以获得更灵活的交换机解析。fykwrbwg2#
首先,perl处理perl解释器的参数,以第一个
--
或非选项参数结束(文件名,除非你使用的是-e
)。该点之后的内容填充@ARGV
。然后,如果存在-s
参数,则会将这些参数处理为选项,在第一个non-option或--
处停止。所以你可以有两个--
的示例,每个示例都发出信号停止处理一组不同的选项,一个用于perl本身,一个用于正在运行的程序。一些例子:eqfvzcg83#
它引用的是第一个
--
script 参数,而不是第一个--
perl
参数。假设
file.pl
以通常,一个人使用
现在,假设您希望
-k
在@ARGV
中结束,而不是被视为选项。所以我们添加一个
--
。组合:
现在,如果你使用
perl -se'...'
代替呢?直到第一个参数不是以-
开始,参数被传递给perl
,而不是-s
或脚本。所以你必须标记参数的结束。-i
由perl
处理,激活就地编辑。-j
被-s
处理,得到$j = 1
。-k
位于@ARGV
中。