我有一个带有shebang的perl脚本
#!/usr/bin/env perl
我希望这个脚本在执行时打印每一行。所以我安装了Devel :: Trace并将脚本shebang更改为
#!/usr/bin/env perl -d:Trace
但这会产生错误,因为它不是有效的语法。
如何同时使用env
功能和tracing
功能?
答案 0 :(得分:10)
这是某些系统上 Just Not Work™的其中一项,特别是那些具有GNU env
的系统。
这是我在perlrun中提到的一个偷偷摸摸的解决方法,我过去曾经使用过这个解决方法:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
print "Hello, world!\n";
这将在您的PATH上找到perl
,您可以在命令行中添加您想要的任何其他开关。您甚至可以在调用perl
之前设置环境变量等。一般的想法是sh
运行eval
,但perl
不运行,而额外的粗略位确保Perl正确找到您的程序并传递所有参数。
#!/bin/sh
FOO=bar; export FOO
#! -*-perl-*-
eval 'exec perl -d:Trace -x -wS $0 ${1+"$@"}'
if 0;
$Devel::Trace::TRACE = 1;
print "Hello, $ENV{FOO}!\n";
如果您使用.pl
扩展名保存文件,则编辑器应检测正确的文件语法,但最初的shebang可能会将其关闭。另一个警告是,如果脚本的Perl部分抛出错误,则行号可能会关闭。
关于这个技巧的巧妙之处在于它也适用于Ruby(可能还有一些其他语言,如Python,还有其他修改):
#!/bin/sh
#! -*-ruby-*-
eval 'exec ruby -x -wS $0 ${1+"$@"}' \
if false
puts "Hello, world!"
希望有所帮助!
答案 1 :(得分:2)
首先,根据操作系统,shebang线的处理方式不同。我在这里谈论GNU / Linux,这是领先的操作系统。 ;)
shebang行将仅分为两部分,解释器(usr / bin / perl)和第二个参数,它应该是文件名参数,它在执行shebanged文件时会自动追加。一些口译员需要这样做。比如#!/usr/bin/awk -f
。
-f
。{/ p>
Perl不需要-f
传递perl文件名,这意味着它就像
perl file.pl
而不是
perl -f file.pl
这为你提供了一个你可以选择的参数开关的基本空间,比如
#!/usr/bin/perl -w
启用警告。此外,由于perl使用getopt()来解析命令行参数,并且getopt()不需要将参数开关用空格分隔,所以只要你不将它们分开就可以传递多个开关,就像这样:
#!/usr/bin/perl -Xw
好吧,只要某个选项获取了一个值,就像-a foo
那样不再有效,而这些选项根本无法通过。没机会。
更灵活的方法是使用这样的shell包装器:
#!/bin/bash
exec perl -a -b=123 ... filename.pl
PS:再次查看您的问题,您一直在询问如何将perl开关与/usr/bin/env perl
一起使用。没有机会。如果您将选项传递给Perl,例如/usr/bin/env perl -w
,Linux将尝试打开解释器'perl -w'
。没有进一步的分裂。
答案 2 :(得分:1)
作为@hek2mgl评论above,一种灵活的方法是使用shell包装器,因为shebang允许一个参数(将是perl
)。一个简单的包装就是这个
#!/bin/bash
env perl -d:Trace "$@"
你可以像这样使用
#!./perltrace
或者您可以创建类似的脚本,并将它们放在perl
所在的任何位置。